1 Commits
main ... alan2

Author SHA1 Message Date
PedroEdiaz
66254e80c9 Fix: Compilation errors alan 2024-11-27 19:31:36 -06:00
31 changed files with 946 additions and 1172 deletions

View File

@@ -2,79 +2,92 @@ BIN = manigraph
OBJ = \ OBJ = \
ext/glad/glad.o \ ext/glad/glad.o \
src/surface.o \
src/context.o \ src/context.o \
src/texture.o \
src/window.o \ src/window.o \
src/matrix.o \
src/shader.o \ src/shader.o \
src/klein.o \
src/input.o \ src/input.o \
src/load.o \
src/mesh.o \ src/mesh.o \
src/main.o src/main.o
EXAMPLES = \
example/basic \
example/riemman \
example/n-cube \
example/n-hilbert-cube \
example/light-cone \
example/lens
CFLAGS = \ CFLAGS = \
-I./ext/cglm/include \ -I./ext/cglm/include \
-I./ext/glfw/include \ -I./ext/glfw/include \
-I./ext/glad \ -I./ext/glad \
-I./include \ -DGLAD \
-Wall -Wno-unused-function -std=c99 -D_GNU_SOURCE \ -Wall -Wno-unused-function -std=c99 -D_GNU_SOURCE \
WAYLAND-LIB = \
xdg-shell \
relative-pointer-unstable-v1 \
xdg-decoration-unstable-v1 \
pointer-constraints-unstable-v1 \
viewporter \
idle-inhibit-unstable-v1 \
fractional-scale-v1 \
xdg-activation-v1 \
wayland
help: help:
@echo "Usage:" @echo "Para compilar el proyecto a tu sistema operativo"
@echo "porfavor usa uno de los siguientes comandos:"
@echo " $(MAKE) windows" @echo " $(MAKE) windows"
@echo " $(MAKE) linux-x11" @echo " $(MAKE) linux-x11"
@echo " $(MAKE) linux-wayland" @echo " $(MAKE) linux-wayland"
@echo " $(MAKE) cocoa" @echo " $(MAKE) cocoa"
@echo " $(MAKE) CC=emcc wasm" @echo " $(MAKE) CC=emcc wasm"
@echo "Examples" @echo "Para limpiar los archivos compilados se puede usar"
@echo " $(MAKE) examples"
@echo "Clean"
@echo " $(MAKE) clean" @echo " $(MAKE) clean"
@echo "Para ejecturar el programa sin instalarlos se puede usar:"
@echo " $(MAKE) run-linux"
src/main.o: src/data/shaders.h src/main.o: src/data/axis.h src/data/shaders.h
windows: $(OBJ) $(OBJ): src/main.h
#cd ext; $(MAKE) -f glfw.mk windows; cd -
$(CC) $(CFLAGS) $(OBJ) -o $(BIN) -L. -lglfw -lopengl32 -lgdi32 # WINDOWS
windows: $(OBJ) glfw.dll
$(CC) $(CFLAGS) $(OBJ) -o $(BIN) -L. -lglfw -lopengl32 -lglew32
glfw.dll: glfw.dll:
$(CC) -fPIC -shared -D_GLFW_WIN32 -D_GLFW_BUILD_DLL ./ext/glfw/src/*.c -o $@ -lgdi32 $(CC) -fPIC -shared -D_GLFW_WIN32 -D_GLFW_BUILD_DLL ./ext/glfw/src/*.c -o $@ -lgdi32
src/main.o: src/data/shaders.h src/data/axis.h
# LINUX # LINUX
linux-wayland: $(OBJ) linux-wayland: $(OBJ)
cd ext; $(MAKE) -f glfw.mk linux-wayland; cd - for i in $(WAYLAND-LIB); \
$(CC) -o $(BIN) $(OBJ) ext/libglfw.a -lm do \
wayland-scanner client-header ext/glfw/deps/wayland/$$i.xml ext/glfw/deps/wayland/$$i-client-protocol.h; \
wayland-scanner private-code ext/glfw/deps/wayland/$$i.xml ext/glfw/deps/wayland/$$i-client-protocol-code.h; \
done
$(MAKE) DFLAGS="-D_GLFW_WAYLAND" libglfw.so
$(CC) -o $(BIN) $(OBJ) -L. -lGLEW -lGL -lglfw -lm
linux-x11: $(OBJ) linux-x11: $(OBJ)
cd ext; $(MAKE) -f glfw.mk linux-x11; cd - $(MAKE) DFLAGS="-D_GLFW_X11" libglfw.so
$(CC) -o $(BIN) $(OBJ) ext/libglfw.a -lm $(CC) -o $(BIN) $(OBJ) -L. -lGLEW -lGL -lglfw -lm
run-linux:
LD_LIBRARY_PATH=. ./$(BIN)
# COCOA
cocoa: $(OBJ) cocoa: $(OBJ)
cd ext; $(MAKE) -f glfw.mk cocoa; cd - $(MAKE) DFLAGS="-D_GLFW_COCOA" libglfw.so
$(CC) -framework OpenGL -o $(BIN) $(OBJ) ext/glfw.a -lGL -lglfw $(CC) -framework OpenGL -o $(BIN) $(OBJ) -L. -lGLEW -lGL -lglfw
wasm: $(OBJ) wasm: $(OBJ)
$(CC) -sUSE_WEBGL2=1 -sUSE_GLFW=3 -o $(BIN).html $(OBJ) $(CC) -sUSE_WEBGL2=1 -sUSE_GLFW=3 -o mani.html $(OBJ)
chmod -x $(BIN).wasm
libglfw.so:
$(CC) -fPIC -shared $(DFLAGS) -D_GLFW_BUILD_DLL -Iext/glfw/deps/wayland ./ext/glfw/src/*.c -o $@
clean: clean:
rm $(OBJ) $(BIN) $(EXAMPLES) rm $(OBJ) $(BIN) ext/glfw/deps/wayland/*.h
cd ext; $(MAKE) -f glfw.mk clean; cd -
examples: $(EXAMPLES)
.SUFFIXES: .c .o .SUFFIXES: .c .o
.c.o: .c.o:
$(CC) -Wno-implicit-function-declaration $(CFLAGS) -c -o $@ $< $(CC) $(CFLAGS) -c -o $@ $<
.c:
$(CC) -I include -o $@ $< -lm

110
README.md
View File

@@ -1,62 +1,92 @@
# Manigraph # Manigraph: Graficadora de variedades
Manigraph is a cutting-edge tool for multidimentional surface visualization, Diaz Camacho Pedro Emilio
capable of handling over a hundred dimensions. It allows users to interactively
explore each dimension in an intuitive and dynamic way.
Import your .klein files, which represents multidimentional surface.
# Building # Resumen
Manigraph is written in C99, and uses OpenGL 2.0 for the rendering. So you just manigraph es un graficador interactiva de variedades que lee archivos binarios, con la información de
need a C compiler to build this project. una variedad multidimensional y grafica esta variedad en una proyección tridimensional.
## Source code # Dependencias
Para poder compilar el proyecto hace falta lo siguiente.
## Programas
- `cc`: Cualquier compilador de C.
- `git`: Gestor de dependencias. (Opcional)
- `make`: Herramienta para compilar automáticamente. (Opcional)
## Librerías
- `openGL`: A cross-platform API for rendering 2D and 3D graphics. (no incluida)
- `glew`: The OpenGL Extension Wrangler Library (no incluida)
- `glfw`: A multi-platform library for OpenGL, OpenGL ES, Vulkan, window and input.
- `cglm`: Highly Optimized 2D / 3D Graphics Math (glm) for C.
### Linux
Para compilar `glfw` en linux hacen falta las siguientes librerías. (no incluidas)
- `x11`: libXcursor-devel libXi-devel libXinerama-devel libXrandr-devel
- `wayland`: libwayland-dev libxkbcommon-dev wayland-protocols
# Descargas
- [git](https://git-scm.com/downloads/win)
- [MinGW](https://github.com/niXman/mingw-builds-binaries/releases)
- [glew](https://glew.sourceforge.net/)
# Clonar el código fuente
``` ```
git clone https://gitea.axiolutions.top/software/manigraph.git git clone https://gitea.adles.top/software/manigraph.git
cd manigraph cd manigraph
git submodule update --init --recursive git submodule update --init --recursive
``` ```
## Dependecies # Compilación
You may need system specific dependecies to build *Manigraph*. Para compilar manualmente el proyecto se puede usar `make` o ejecutar los comandos manualmente
[Reference](https://www.glfw.org/docs/3.3/compile.html#compile_deps) en el código fuente de `manigraph`.
### Linux ## Make
- `x11`: libXcursor-devel libXi-devel libXinerama-devel libXrandr-devel Los siguientes comandos sirven para compilar `manigraph` deacuerdo al sistema operativo.
- `wayland`: libwayland-dev libxkbcommon-dev wayland-protocols
## Commands
A C compiler is needed for building *Manigraph*. and any of those commands
``` ```
make windows make windows
./compile.bat
make linux-x11 make linux-x11
make linux-wayland make linux-wayland
make cocoa make cocoa
make CC=emcc wasm
``` ```
# Flow of Manigraph ## Manualmente
![Flow of Manigraph](doc/flow.svg) se pueden compilar el proyecto manualmente sin necesidad del programa `make`.
# Design ### GLFW
Manigraph is a program designed with sustainability in mind. It is built to be Si tienes problemas compilando `GLFW` puedes checar su página web oficial
portable, resource-efficient, and easy to maintain and scale. The program explicando el tema: [Compiling GLFW](https://www.glfw.org/docs/3.3/compile.html).
follows a Data-Oriented Programming (DOP) paradigm, where each file is
responsible for a specific data type and manages its own dependencies. Each
function is named after the file it resides in, ensuring a clear organization
and structure.
The independence of data types allows for efficient scaling and maintenance. #### Windows
The main file is a special case in this design: it is responsible for combining ```
all the data types in a comprehensive manner, actng as the workflow of the program. cc -fPIC -shared -D_GLFW_WIN32 -D_GLFW_BUILD_DLL ./ext/glfw/src/*.c -o glfw.dll -lgdi32
```
# Contributing #### Linux
Before commiting use `clang-format`, for coding style consistency. Your ```
contribution must be whitin the design principles and the concept of Manigraph. cc -fPIC -shared -D_GLFW_X11 -D_GLFW_BUILD_DLL ./ext/glfw/src/*.c -o libglfw.so
cc -fPIC -shared -D_GLFW_WAYLAND -D_GLFW_BUILD_DLL ./ext/glfw/src/*.c -o libglfw.so
```
The following diagram illustrates the relationships between files, showing how #### Mac
they are connected through dependencies. It also highlights the scenarios where ```
files are not independent of one another, cc -fPIC -shared -D_GLFW_COCOA -D_GLFW_BUILD_DLL ./ext/glfw/src/*.c -o libglfw.so
```
![File layout](doc/file_layout.svg) ### Manigraph
#### Windows
```
cc -I ext/cglm/include/ -I ext/glfw/include/ src/*.c -o manigraph -L. -lglfw -lopengl32 -lglew32
```
#### Linux
```
cc -I ext/cglm/include/ -I ext/glfw/include/ src/*.c -o manigraph -L. -lglfw -lGL -lGLEW
```
#### Mac
```
cc -framework GL -I ext/cglm/include/ -I ext/glfw/include/ src/*.c -o manigraph -L. -lglfw -lGLEW
```
# Ejecutar
En linux se puede ejecutar el programa sin instalar la libreria de glfw usando:
```
LD_LIBRARY_PATH=. ./manigraph
```

View File

@@ -0,0 +1,80 @@
# Estructura de archivos
Díaz Camacho Pedro Emilio
# Headers
## main.h
Este archivo incluye los prototipos internos, que va a usar el programa
funge como api interna para los desarrolladores y debe estar bien documentada.
# codigo fuente
## main.c
Este archivo debe configurar el programa antes de iniciarse, avisar de los problemas
que eviten que el programa se ejecute correctamente, iniciar y terminar los objetos que use el
programa, así como ejecutar la función principal
### Depende de
- <GL/gl.h>
## context.c
En este archivo se escoge un color para limpiar la pantalla y tiene una función para limpiar
tanto lo dibujado en pantalla, como distintos buffers gráficos.
### Depende de
- <GL/gl.h>
## input.c
Incluye la función `poll_input`, que se ejecuta en cada ciclo del programa y devuelve un
cuaternion de tipo `float *` que representa la rotación total del cubo, después de interactuar
con el programa.
### Depende de
- <GLFW/glfw3.h>
- <cglm/quat.h>
## matrix.c
Incluye las funciónes para configurar y cargar en la GPU las 3 matrices principales.
- `fix_matrix` esta matriz no cambia y se usa para configurar la perspectiva y la vista que
va a usar el programa en todo momento.
- `mdl_matrix` esta matriz depende de cada mesh y describe la rotación única de cada objeto,
se usa para rotar los ejes ortogonamente con un indice.
- `rot_matrix` esta matriz describe la rotación total de todos los objetos y se configura con
un cuaternio
### Depende de
- <cglm/mat4.h>
- <cglm/cam.h>
- <cglm/quat.h>
## mesh.c
Este archivo se usa para crear, destruir y dibujar objetos de tipo `mesh`, un `mesh` es una
colección de triángulos que describen un objeto multidimensional.
### Depende de
- <GL/gl.h>
- <stdlib.h>
## shader.c
Debe crear, destruir y usar los shaders, estos shaders son programas para la gpu escritos en glsl para
además aquí se carga memoria en gpu con las funciónes `gload_`
### Depende de
- <GL/gl.h>
## texture.c
Debe cargar, usar y destruir las texturas, que va a usar la gpu, también crea una textura
para una paleta de colores definida, esto para manipular fácilmente los colores que usará el programa.
### Depende de
- <GL/gl.h>
## window.c
Crea, usa, limpie y cierra una ventana, una ventana tiene un contexto de OpenGL asociado para poder
dibujar objetos en ella, tiene una función especial para avisar si la ventana está abierta para
dibujar.
### Depende de
- <GLFW/glfw3.h>
# Datos
## data/cube.h
Aquí esta la información del mesh de un cubo, este se va a borrar cuando podamos
importar meshes para graficarlos.
## data/axis.h
Aquí está el mesh de un solo eje, este se va a rotar para hacer los otros 2 ejes.
## data/shaders.h
Aquí estan los shaders en glsl para dibujar en pantalla

43
doc/es/dev/tipos.md Normal file
View File

@@ -0,0 +1,43 @@
# Tipos de datos del proyecto
Díaz Camacho Pedro Emilio
# Introducción
En este archivo vamos a detallar los tipos de datos únicos del programa, estos
tipos de datos son estructuras que representan objetos computacionales y son
necesarios para integrar las distintas partes del programa.
## window_t
En `window.c` tenemos una estructura que es la ventana y esta se representa por `window_t`,
este tipo de dato es un pointer que es manejado por `glfw`.
## id_t
`id_t` es un tipo de dato que representa objetos de `OpenGL`, estos datos
normalmente vienen enumerados, y en `manigraph` se usan para representar `shaders`,
`programs` y `texture`.
## mesh_t
Este es un tipo de dato usado para interactuar con `mesh.c`, este representa la triangulación de un
objeto gráfico y funciona ocultando las variables que `OpenGL` necesita en un `void *`.
## mat4_t
`mat4_t` se usará para representar las matrices, se usará este tipo de dato exclusivamente
en `matrix.c` y funcionará con el tipo de dato `mat4` de `cglm`.
## quat_t
Este tipo de dato sirve para representar un quaternio, este quaternio representa la rotación
del objeto gráficado en la proyección tridimensional, y se usará para crear una matriz que
pueda entender `glsl`.
## narray
`narray` es un tipo de dato que funciona como un `array` enumerado, esto significa que el primer
elemento del `array` dice cuantos elementos tiene este, sin contar el primer elemento, y los demas elementos
funcionan como un `array` normal.
esta estructura nos ayuda a trabajar con arrays de tamaños arbitrario de forma óptima y sin tener que marcar el
último elemento de forma especial.
### narray_u8_t
es un `narray` para `char` y `unsigned char`.
### narray_float_t
es un `narray` para `float`.

59
doc/es/tech/diseno.md Normal file
View File

@@ -0,0 +1,59 @@
# Manual de Diseño
Diaz Camacho Pedro Emilio
# Objetivos
## Prioridad alta
- [ ] El programa debe actualizarse cuando interactuan con el.
- [ ] El usuario quiere:
- [X] Ver 3 ejes en todo momento.
- [ ] Ver que ejes esta viendo.
- [ ] Ver cuantos ejes hay.
- [X] El usuario quiere:
- [X] Rotar estos ejes,
- [X] Ver donde quedan los ejes despues de la rotados.
- [ ] El usuario experimentado quiere ejecutar el programa y pasar la variedad:
- [ ] Como argumento del programa.
- [ ] Desde la entrada estandar del programa.
## Prioridad media
- [ ] El usuario quiere:
- [ ] Cambiar los ejes que se ven por pares.
- [ ] Cambiar los ejes donde esta la informacion de los ejes.
- [ ] El usuario quiere interactuar con el programa:
- [ ] Usando solo el mouse.
- [ ] Usando solo el teclado.
## Prioridad baja
- [ ] El usuario quiere guardar las transformaciones como un archivo GIF.
# Camino
0. Graficadora de un cubo.
1. Se hace un programa que muestre un cubo.
1. Se muestran los 3 ejes del cubo
1. Se rota el cubo en sus 3 ejes usando el teclado.
1. Se rota el cubo en sus 3 ejes usando el mouse.
1. Se muestran la etiqueta de los ejes.
1. Se hace el formato de objetos multidimensionales.
0. Programa ejemplo
1. Se hace un programa que divida un cuadrado en triangulos.
1. Se mapea cada vertice del triangulo en un punto de la cinta de
mobius usando una parametrizacion
1. Se mapea cada vertice del triangulo en un punto de la botella de
klein usando una parametrizacion
1. Se divide cada lado de un cubo de n dimensiones, en triangulos.
0. Graficadora de variedades
1. Se generaliza el programa para usar este formato.
1. Se muestran la informacion de los ejes mostrados y cuantos hay.
1. Se pueden cambiar los ejes por pares
1. Usando el mouse.
1. Usando el teclado.
0. Detalles.
1. Se anima el cambio de eje.
1. Se hace el generador de GIF.
1. Se puede cambiar el shader
1. Documentacion

22
doc/es/tech/problemas.md Normal file
View File

@@ -0,0 +1,22 @@
# Problemas esperados al desarrollar
Diaz Camacho Pedro Emilio
## OpenGL esperan objetos tridimensionales, no de n dimensiones.
Usando glVertexAttribPointer podemos pasar las coordenadas que
queramos de los puntos de las variedades, y con ello usar objetos 3D en
el shader.
## Rotar ejes por pares en una animacion continua.
- Con glVertexAttribPointer podemos pasar las coordenadas del eje
seleccionado, al shader.
- Con la funcion mix del shader y bloqueando el input, podemos hacer
una animacion pasando una variable con la cpu.
- Cuando la animacion termine intercambiar los indices del layout,
usando glVertexAttribPointer otra vez.
## Volumen de la variedad.
Dado que la funcion parametrizadora es continua, mandamos la frontera
de un n-cubo a la frontera de una variedad, por lo que solo basta
graficar la frontera de la variedad.

19
doc/es/user.md Normal file
View File

@@ -0,0 +1,19 @@
# Manual de usario para Manigraph
Manigraph es un graficador interactivo de variedades que lee archivos
binarios de una variedad multidimensional y los proyecta a 3 dimensiones.
# Glosario
Llamaremos a los 3 ejes de la proyección tridimensional `X`, `Y` y `Z`,
este sistema de coordenadas es derecho con el eje `Z` apuntando afuera de la pantalla
# Controles
## Teclado
- `Q` Rota el eje `X` de forma horaria.
- `W` Rota el eje `X` de forma antihoraria.
- `A` Rota el eje `Y` de forma horaria.
- `S` Rota el eje `Y` de forma antihoraria.
- `Z` Rota el eje `Z` de forma horaria.
- `X` Rota el eje `Z` de forma antihoraria.
## Mouse
- Hacer `click` en un eje lo selecciona.
- El `scroll` del mouse hace girar al eje seleccionado.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 39 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 107 KiB

View File

@@ -1,95 +0,0 @@
#include <math.h>
#include <stdio.h>
#define KLEIN_IMPLEMENT
#include <klein/klein.h>
#include <klein/norm.h>
#include <klein/parm.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
void cube(float *d_surface, int *coord, unsigned char *grid)
{
int i;
for (i = 0; i < 4; i++)
d_surface[i] = (2 * (float)coord[i] / grid[i]) - 1;
if (4 == 2)
d_surface[2] = 0;
}
void mobius(float *d_surface, int *coord, unsigned char *grid)
{
const float width = 0.5;
float u = (2 * M_PI) * ((float)coord[0] / grid[0]);
float v = (2 * width) * ((float)coord[1] / grid[1]) - width;
d_surface[0] = cos(u) + v * cos(u / 2) * cos(u);
d_surface[1] = sin(u) + v * cos(u / 2) * sin(u);
d_surface[2] = v * sin(u / 2);
}
void torus(float *d_surface, int *coord, unsigned char *grid)
{
float u = (M_PI) * ((float)coord[0] / grid[0]) + M_PI;
float v = (2 * M_PI) * ((float)coord[1] / grid[1]);
d_surface[0] = (1 + 0.5 * cos(v)) * cos(u);
d_surface[1] = (1 + 0.5 * cos(v)) * sin(u);
d_surface[2] = 0.5 * sin(v);
}
void klein(float *d_surface, int *coord, unsigned char *grid)
{
float u = (2 * M_PI) * ((float)coord[0] / grid[0]);
float v = (2 * M_PI) * ((float)coord[1] / grid[1]);
d_surface[0] = (0.5 * cos(v) + 0.5) * cos(u);
d_surface[1] = (0.5 * cos(v) + 0.5) * sin(u);
d_surface[2] = sin(v) * cos(u / 2);
d_surface[3] = sin(v) * sin(u / 2);
}
int main(void)
{
unsigned char i = 0;
const char *file_name[] = {"mobius.klein", "torus.klein", "klein.klein"};
struct parm parametrization[] = {
{
.grid = (unsigned char[]){16, 4},
.m = 2,
.n = 3,
.f = mobius,
},
{
.grid = (unsigned char[]){16, 8},
.m = 2,
.n = 3,
.f = torus,
},
{
.grid = (unsigned char[]){16, 16},
.m = 2,
.n = 4,
.f = klein,
},
};
for (i = 0; i < 4; ++i)
{
struct klein klein;
printf("writing %s\n", file_name[i]);
klein_parametrize(&klein, parametrization[i]);
klein_normalize(&klein);
klein_export_file(klein, file_name[i]);
free(klein.vertex);
free(klein.normals);
}
return 0;
}

View File

@@ -1,54 +0,0 @@
#include <math.h>
#include <stdio.h>
#define KLEIN_IMPLEMENT
#include <klein/klein.h>
#include <klein/norm.h>
#include <klein/parm.h>
int p = 37;
int q = 7;
void lens(float *d_surface, int *coord, unsigned char * grid)
{
float norm = 0;
float sphere[4];
for (int i = 0; i < 4; i++)
sphere[i] = ((float)coord[i] / grid[i]) - 0.5;
for(int i = 0; i < 4; i++)
norm += sphere[i] * sphere[i];
for (int i = 0; i < 4; i++)
sphere[i] = sphere[i] / sqrt(norm);
d_surface[0] = (sphere[0] * cos(2 * M_PI / p)) - (sphere[1] * sin(2 * M_PI / p));
d_surface[1] = (sphere[0] * sin(2 * M_PI / p)) + (sphere[1] * cos(2 * M_PI / p));
d_surface[2] = (sphere[2] * cos(2 * M_PI * q / p)) - (sphere[3] * sin(2 * M_PI * q / p));
d_surface[3] = (sphere[2] * sin(2 * M_PI * q / p)) + (sphere[3] * cos(2 * M_PI * q / p));
}
int main(void)
{
char file_name[0xff];
struct klein klein;
struct parm parametrization = {
.grid = (unsigned char[]){8, 8,8,8},
.m = 4,
.n = 4,
.f = lens,
};
snprintf(file_name, 0xff, "lens-%03d-%03d.klein", p, q);
printf("writing %s\n", file_name);
klein_parametrize(&klein, parametrization);
klein_normalize(&klein);
klein_export_file(klein, file_name);
free(klein.vertex);
free(klein.normals);
return 0;
}

View File

@@ -1,50 +0,0 @@
#include <math.h>
#include <stdio.h>
#define KLEIN_IMPLEMENT
#include <klein/klein.h>
#include <klein/norm.h>
#include <klein/parm.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
unsigned char dim = 17;
void cube(float *d_surface, int *coord, unsigned char *grid)
{
int i;
for (i = 0; i < dim; i++)
d_surface[i] = (2 * (float)coord[i] / grid[i]) - 1;
if (dim == 2)
d_surface[2] = 0;
}
int main(void)
{
unsigned char i;
char file_name[0xff];
struct klein klein;
struct parm parametrization = {
.m = dim,
.n = dim,
.f = cube,
};
parametrization.grid = malloc(dim);
for (i = 0; i < dim; ++i)
parametrization.grid[i] = 1 + i;
snprintf(file_name, 0xff, "cube-%03d.klein", dim);
printf("writing %s\n", file_name);
klein_parametrize(&klein, parametrization);
klein_normalize(&klein);
klein_export_file(klein, file_name);
return 0;
}

View File

@@ -1,50 +0,0 @@
#include <complex.h>
#include <math.h>
#include <stdio.h>
#define KLEIN_IMPLEMENT
#include <klein/klein.h>
#include <klein/norm.h>
#include <klein/parm.h>
#ifndef CMPLX
#define CMPLX(a, b) (a + I * b)
#endif
complex float f(complex float z) { return csqrt(z); }
void riemman(float *d_surface, int *coords, unsigned char *grid)
{
complex float eq;
float u = 2 * ((float)coords[0] / grid[0]) - 1;
float v = 2 * ((float)coords[1] / grid[1]) - 1;
eq = f(CMPLX(u, v));
d_surface[0] = u;
d_surface[1] = v;
d_surface[2] = creal(eq);
d_surface[3] = cimag(eq);
}
int main(void)
{
const char *file_name = "riemman.klein";
struct klein klein;
struct parm parametrization = {
.grid = (unsigned char[]){16, 4},
.m = 2,
.n = 4,
.f = riemman,
};
printf("writing %s\n", file_name);
klein_parametrize(&klein, parametrization);
klein_normalize(&klein);
klein_export_file(klein, file_name);
free(klein.vertex);
free(klein.normals);
return 0;
}

View File

@@ -1,71 +0,0 @@
BIN = libglfw.a
OBJ = \
glfw/src/context.o \
glfw/src/egl_context.o \
glfw/src/glx_context.o \
glfw/src/init.o \
glfw/src/input.o \
glfw/src/linux_joystick.o \
glfw/src/monitor.o \
glfw/src/null_init.o \
glfw/src/null_joystick.o \
glfw/src/null_monitor.o \
glfw/src/null_window.o \
glfw/src/osmesa_context.o \
glfw/src/platform.o \
glfw/src/posix_module.o \
glfw/src/posix_poll.o \
glfw/src/posix_thread.o \
glfw/src/posix_time.o \
glfw/src/vulkan.o \
glfw/src/wgl_context.o \
glfw/src/win32_init.o \
glfw/src/win32_joystick.o \
glfw/src/win32_module.o \
glfw/src/win32_monitor.o \
glfw/src/win32_thread.o \
glfw/src/win32_time.o \
glfw/src/win32_window.o \
glfw/src/window.o \
glfw/src/wl_init.o \
glfw/src/wl_monitor.o \
glfw/src/wl_window.o \
glfw/src/x11_init.o \
glfw/src/x11_monitor.o \
glfw/src/x11_window.o \
glfw/src/xkb_unicode.o
WAYLAND-LIB = \
xdg-shell \
relative-pointer-unstable-v1 \
xdg-decoration-unstable-v1 \
pointer-constraints-unstable-v1 \
viewporter \
idle-inhibit-unstable-v1 \
fractional-scale-v1 \
xdg-activation-v1 \
wayland
windows:
$(MAKE) $(OBJ) CFLAGS="-D_GLFW_WIN32 -Iglfw/deps/wayland"
$(AR) rsc $(BIN) $(OBJ)
linux-x11:
$(MAKE) $(OBJ) CFLAGS="-D_GLFW_X11 -Iglfw/deps/wayland"
$(AR) rsc $(BIN) $(OBJ)
linux-wayland:
for i in $(WAYLAND-LIB); \
do \
wayland-scanner client-header glfw/deps/wayland/$$i.xml glfw/deps/wayland/$$i-client-protocol.h; \
wayland-scanner private-code glfw/deps/wayland/$$i.xml glfw/deps/wayland/$$i-client-protocol-code.h; \
done
$(MAKE) $(OBJ) CFLAGS="-D_GLFW_WAYLAND -fPIC -Iglfw/deps/wayland"
$(AR) rsc $(BIN) $(OBJ)
clean:
rm $(OBJ) $(BIN)
rm glfw/deps/wayland/*.h

View File

@@ -1,50 +0,0 @@
#ifdef KLEIN_H
#error file included twice
#endif
#define KLEIN_H
#include <stdint.h>
#ifdef KLEIN_IMPLEMENT
#include <stdio.h>
#include <stdlib.h>
#endif
struct klein
{
float *vertex, *normals;
uint64_t vertex_size;
uint8_t dim;
};
/*
The klein format must have:
5 bytes with klein.
1 byte empty for expantions
1 byte with the dimention of the surface
*/
static inline
int klein_export_file(struct klein klein, const char * filename);
#ifdef KLEIN_IMPLEMENT
static inline
int klein_export_file(struct klein klein, const char * filename)
{
FILE *file = fopen(filename, "wb");
if (!file)
return 1;
fwrite("KLEIN", 1, 5, file);
fwrite("\0", 1, 1, file);
fwrite(&klein.dim, 1, 1, file);
fwrite(&klein.vertex_size, 8, 1, file);
fwrite(klein.vertex, 4, klein.vertex_size * klein.dim, file);
fwrite(klein.normals, 4, klein.vertex_size * klein.dim, file);
fclose(file);
return 0;
}
#endif

View File

@@ -1,132 +0,0 @@
#ifdef KLEIN_NORM_H
#error file included twice
#endif
#define KLEIN_NORM_H
#ifndef KLEIN_H
#warning Please include klein/klein.h
#endif
void klein_normalize(struct klein * klein);
#ifdef KLEIN_IMPLEMENT
static inline
void __calculate_normal( float *p1, float *p2, float *p3, float *normal, unsigned char n)
{ unsigned char i;
float alpha;
float *v1, *v2, *v3;
float *u1, *u2, *u3;
v1 = malloc(n * sizeof(float));
v2 = malloc(n * sizeof(float));
v3 = malloc(n * sizeof(float));
u1 = malloc(n * sizeof(float));
u2 = malloc(n * sizeof(float));
u3 = malloc(n * sizeof(float));
/*
Calculate a normal vector of a plain using Gram-Schmidt process
*/
{
for (i = 0; i < n; ++i)
{
v1[i] = p2[i] - p1[i];
v2[i] = p3[i] - p1[i];
v3[i] = p1[i];
}
for (i = 0; i < n; ++i)
{
u1[i] = v1[i];
}
{
float proj[n];
float dot_v2_u1 = 0.0f, dot_u1_u1 = 0.0f;
for (i = 0; i < n; ++i)
{
dot_v2_u1 += v2[i] * u1[i];
dot_u1_u1 += u1[i] * u1[i];
}
alpha = dot_v2_u1 / dot_u1_u1;
for (i = 0; i < n; ++i)
{
proj[i] = u1[i] * alpha;
u2[i] = v2[i] - proj[i];
}
}
{
float proj1[n], proj2[n];
float dot_v3_u1 = 0.0f, dot_u1_u1 = 0.0f;
float dot_v3_u2 = 0.0f, dot_u2_u2 = 0.0f;
for (i = 0; i < n; ++i)
{
dot_v3_u1 += v3[i] * u1[i];
dot_u1_u1 += u1[i] * u1[i];
}
for (i = 0; i < n; ++i)
{
proj1[i] = u1[i] * (dot_v3_u1 / dot_u1_u1);
}
for (i = 0; i < n; ++i)
{
dot_v3_u2 += v3[i] * u2[i];
dot_u2_u2 += u2[i] * u2[i];
}
for (i = 0; i < n; ++i)
{
proj2[i] = u2[i] * (dot_v3_u2 / dot_u2_u2);
u3[i] = v3[i] - proj1[i] - proj2[i];
}
}
float magnitude = 0.0f;
for (i = 0; i < n; ++i)
{
magnitude += u3[i] * u3[i];
}
magnitude = sqrtf(magnitude);
for (i = 0; i < n; ++i)
{
normal[i] = u3[i] / magnitude;
}
free(v1);
free(v2);
free(v3);
free(u1);
free(u2);
free(u3);
return;
}
}
void klein_normalize(struct klein * klein)
{
unsigned long i;
unsigned char j;
float *norm_vec;
klein->normals = malloc((klein->dim * klein->vertex_size) * sizeof(float));
norm_vec = malloc(klein->dim * sizeof(float));
for (i = 0; i < klein->vertex_size; i += 3 * klein->dim)
{
__calculate_normal(klein->vertex + i, klein->vertex + i + klein->dim, klein->vertex + i + 2 * klein->dim, norm_vec, klein->dim);
for (j = 0; j < klein->dim; ++j )
{
(klein->normals + i)[j]=norm_vec[j];
(klein->normals + i + klein->dim)[j]=norm_vec[j];
(klein->normals + i + 2*klein->dim)[j]=norm_vec[j];
}
}
free(norm_vec);
}
#endif

View File

@@ -1,136 +0,0 @@
#ifndef KLEIN_H
#warning Please include klein/klein.h before klein/parm.h
#endif
#ifdef KLEIN_PARM_H
#error file included twice
#endif
#define KLEIN_PARM_H
typedef void (*function_t)(float *, int *, unsigned char *);
struct parm
{
unsigned char *grid;
unsigned char m, n;
function_t f;
};
void klein_parametrize( struct klein * klein, struct parm parm );
#ifdef KLEIN_IMPLEMENT
#ifdef TEST
#include <assert.h>
#endif
static inline uint64_t __factorial(uint64_t n)
{
if (n == 1)
return 1;
return n * __factorial(n - 1);
}
static inline uint64_t __face(int n)
{
if (n == 2)
return 1;
return (1 << (n - 3)) * __factorial(n) / __factorial(n - 2);
}
void klein_parametrize( struct klein * klein, struct parm parm)
{
unsigned long i, j, o, p, n;
uint64_t k, size, q = 0;
int *face;
#ifdef TEST
assert(__face(2) == 1);
assert(__face(3) == 6);
assert(__face(4) == 24);
#endif
klein->dim = parm.n;
klein->vertex_size = 0;
{
uint64_t test = 0;
for (o = 0; o < parm.m; o++)
for (p = 0; p < o; p++)
test += 1;
for (o = 0; o < parm.m; o++)
for (p = 0; p < o; p++)
klein->vertex_size += (uint64_t)parm.grid[p] * parm.grid[o] * 6 * __face(parm.m)/test;
}
size = klein->vertex_size*klein->dim;
klein->vertex = malloc(size * sizeof(float));
face = malloc(parm.m * sizeof(int));
for (o = 0; o < parm.m; o++)
{
for (p = 0; p < o; p++)
{
for (k = 0; k < ((uint64_t)1 << (parm.m - 2)); k++)
{
unsigned char skip = 0;
for (n = 0; n < parm.m; n++)
{
if (n == o || n == p)
skip++;
face[n] = (k & ((uint64_t)1 << (n - skip))) ? parm.grid[n] : 0;
}
for (i = 0; i < parm.grid[p]; i++)
{
for (j = 0; j < parm.grid[o]; j++)
{
face[p] = i;
face[o] = j;
parm.f(&klein->vertex[q], face, parm.grid);
q += parm.n;
face[p] = i + 1;
face[o] = j;
parm.f(&klein->vertex[q], face, parm.grid);
q += parm.n;
face[p] = i + 1;
face[o] = j + 1;
parm.f(&klein->vertex[q], face, parm.grid);
q += parm.n;
face[p] = i;
face[o] = j;
parm.f(&klein->vertex[q], face, parm.grid);
q += parm.n;
face[p] = i;
face[o] = j + 1;
parm.f(&klein->vertex[q], face, parm.grid);
q += parm.n;
face[p] = i + 1;
face[o] = j + 1;
parm.f(&klein->vertex[q], face, parm.grid);
q += parm.n;
}
}
}
}
}
#ifdef TEST
assert(q == size);
#endif
}
#endif

View File

@@ -3,13 +3,18 @@
#ifdef EMSCRIPTEN #ifdef EMSCRIPTEN
#include <GL/gl.h> #include <GL/gl.h>
#else #else
#ifdef GLAD
#include <glad.h> #include <glad.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#else
#include <GL/glew.h>
#endif
#endif #endif
void set_clean_color_context(unsigned char r, unsigned char g, unsigned char b) void set_clean_color_context(unsigned char r, unsigned char g, unsigned char b)
{ {
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glClearColor((float)r / 0xff, (float)g / 0xff, (float)b / 0xff, 1.0); glClearColor((float)r / 0xff, (float)g / 0xff, (float)b / 0xff, 1.0);
} }
@@ -18,7 +23,12 @@ int init_context(void)
#ifdef EMSCRIPTEN #ifdef EMSCRIPTEN
return 1; return 1;
#else #else
#ifdef GLAD
return gladLoadGLLoader((GLADloadproc)glfwGetProcAddress); return gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
#else
return glewInit();
#endif
#endif #endif
} }

40
src/data/axis.h Normal file
View File

@@ -0,0 +1,40 @@
#undef A
#undef B
#undef C
#undef D
#undef E
#undef F
#undef G
#undef H
#define A -2.0,-0.05,-0.05,
#define B -2.0,-0.05, 0.05,
#define C -2.0, 0.05,-0.05,
#define D -2.0, 0.05, 0.05,
#define E 2.0,-0.05,-0.05,
#define F 2.0,-0.05, 0.05,
#define G 2.0, 0.05,-0.05,
#define H 2.0, 0.05, 0.05,
float d_axis[] =
{
3*3*2*6,
A C E
G E C
E G F
H F G
F H B
D B H
B D A
C A D
C D G
H G D
E B A
B E F
};

View File

@@ -1,4 +1,4 @@
const char *vs = const char * vs =
#ifdef EMSCRIPTEN #ifdef EMSCRIPTEN
"#version 300 es\n" "#version 300 es\n"
"precision highp float;" "precision highp float;"
@@ -15,84 +15,79 @@ const char *vs =
"layout (location = 6) in float aNormal_z;" "layout (location = 6) in float aNormal_z;"
"layout (location = 7) in float aNormal_w;" "layout (location = 7) in float aNormal_w;"
"uniform float angle;" "uniform float idx;"
"uniform float i;"
"uniform vec4 color;"
"uniform mat4 fix;" "uniform mat4 fix;"
"uniform mat4 rot;" "uniform mat4 rot;"
"uniform mat4 mdl;"
"out float index;"
"out vec3 Normal;" "out vec3 Normal;"
"out vec3 FragPos;" "out vec3 FragPos;"
"out vec4 Color;"
"mat2 rotate2d( float angle )"
"{"
"return mat2( cos(angle), sin(angle), -sin(angle), cos(angle) );"
"}"
"void main()" "void main()"
"{" "{"
" Color=color;" " index=idx;"
" vec3 aNormal = vec3(aNormal_x,aNormal_y,aNormal_z);" " vec3 aNormal = vec3(aNormal_x,aNormal_y,aNormal_z);"
" vec3 aPos = vec3(aPos_x,aPos_y,aPos_z);" " vec3 aPos = vec3(aPos_x,aPos_y,aPos_z);"
" Normal = mat3(transpose(inverse(rot*mdl))) * aNormal;"
" aNormal[int(i)] = (vec2(aNormal[int(i)], aNormal_w) * " " gl_Position = fix * rot * mdl * vec4( aPos, 1.0 );\n"
"rotate2d(angle))[0];" " FragPos = vec3( rot * mdl * vec4(aPos, 1.0));"
" aPos[int(i)] = (vec2(aPos[int(i)], aPos_w) * rotate2d(angle))[0];"
" Normal = mat3(transpose(inverse(rot))) * aNormal;"
" gl_Position = fix * rot * vec4( aPos, 1.0 );\n"
" FragPos = vec3( rot * vec4(aPos, 1.0));"
"}"; "}";
const char *fs_plain =
const char * fs_plain =
#ifdef EMSCRIPTEN #ifdef EMSCRIPTEN
"#version 300 es\n" "#version 300 es\n"
"precision highp float;" "precision highp float;"
"precision highp sampler2DArray;"
#else #else
"#version 330 core\n" "#version 330 core\n"
#endif #endif
"uniform sampler2DArray palette;"
"in float index;"
"out vec4 FragColor;" "out vec4 FragColor;"
"in vec3 Normal;" "in vec3 Normal;"
"in vec3 FragPos;" "in vec3 FragPos;"
"in vec4 Color;"
"void main()" "void main()"
"{" "{"
" FragColor = vec4(pow(vec3(Color),vec3(1.0/1.0)),Color.a);" " FragColor = texture( palette, vec3( 0, 0, index ) ).rgba;"
"}"; "}";
const char *fs = const char * fs =
#ifdef EMSCRIPTEN #ifdef EMSCRIPTEN
"#version 300 es\n" "#version 300 es\n"
"precision highp float;" "precision highp float;"
"precision highp sampler2DArray;"
#else #else
"#version 330 core\n" "#version 330 core\n"
#endif #endif
"in vec3 Normal;" "uniform sampler2DArray palette;"
"in vec3 FragPos;"
"in vec4 Color;"
"out vec4 FragColor;" "in float index;"
"in vec3 Normal;"
"in vec3 FragPos;"
"void main()" "out vec4 FragColor;"
"{"
" vec3 viewPos = vec3(0, 0, -15);\n" "void main()"
" vec3 viewDir = normalize(viewPos - FragPos);\n" "{"
" vec4 color = texture(palette, vec3(0, 0, index));\n"
" vec3 lightPos = viewPos;\n" " vec3 viewPos = vec3(0, 0, -15);\n"
" vec3 lightDir = normalize(lightPos - FragPos);\n" " vec3 viewDir = normalize(viewPos - FragPos);\n"
" vec3 halfwayDir = normalize(lightDir + viewDir);\n" " vec3 lightPos = viewPos;\n"
" vec3 lightDir = normalize(lightPos - FragPos);\n"
" float specular = pow(abs(dot(normalize(Normal), halfwayDir)), 32.0);\n" " vec3 halfwayDir = normalize(lightDir + viewDir);\n"
" float diffuse = abs(dot(normalize(Normal), lightDir));\n"
" vec3 result = pow((0.5 + 0.5*diffuse + 1*specular) * Color.rgb, " " float specular = pow(max(dot(normalize(Normal), halfwayDir), 0.0), 16.0);\n"
"vec3(1.0/2.2));\n" " float diffuse = max(dot(normalize(Normal), lightDir), 0.0);\n"
" FragColor = vec4(result, Color.a);\n"
"}"; " vec3 result = (0.5 + 0.5 * diffuse + specular) * color.rgb;\n"
" FragColor = vec4(result, color.a);\n"
"}";

View File

@@ -1,5 +1,4 @@
#include "main.h" #include "main.h"
#include <glad.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <cglm/quat.h> #include <cglm/quat.h>
#include <stdio.h> #include <stdio.h>
@@ -10,9 +9,7 @@ unsigned char selected_axis = 0;
int window_width; int window_width;
int window_height; int window_height;
static versor q = GLM_QUAT_IDENTITY_INIT; versor q = GLM_QUAT_IDENTITY_INIT;
unsigned char animate_index = 0;
vec3 axis[3] = { vec3 axis[3] = {
{1, 0, 0}, {1, 0, 0},
@@ -22,23 +19,6 @@ vec3 axis[3] = {
extern struct projection projection; extern struct projection projection;
static inline
void __input_update_q(versor p)
{
glm_quat_mul(p, q, q);
glm_quat_rotatev(p, axis[0], axis[0]);
glm_quat_rotatev(p, axis[1], axis[1]);
glm_quat_rotatev(p, axis[2], axis[2]);
glm_quat_normalize(q);
}
void __error_callback_input(int x, const char * msg )
{
mlog("[GLFW] ");
mlog(msg);
mlog("\n");
}
void __key_callback_input( void __key_callback_input(
GLFWwindow *window, int key, int scancode, int action, int mods) GLFWwindow *window, int key, int scancode, int action, int mods)
{ {
@@ -60,7 +40,7 @@ void __key_callback_input(
if (selected_coord == projection.z) if (selected_coord == projection.z)
return; return;
projection.w = selected_coord; selected_coord = projection.w;
} }
if (projection.w >= projection.m) if (projection.w >= projection.m)
@@ -69,30 +49,25 @@ void __key_callback_input(
switch (key) switch (key)
{ {
unsigned char tmp; unsigned char tmp;
case GLFW_KEY_Z:
case GLFW_KEY_P:
tmp = projection.w; tmp = projection.w;
projection.w = projection.x; projection.w = projection.x;
projection.x = tmp; projection.x = tmp;
animate_index = 1;
break; break;
case GLFW_KEY_X: case GLFW_KEY_O:
tmp = projection.w; tmp = projection.w;
projection.w = projection.y; projection.w = projection.y;
projection.y = tmp; projection.y = tmp;
animate_index = 2;
break; break;
case GLFW_KEY_C: case GLFW_KEY_I:
tmp = projection.w; tmp = projection.w;
projection.w = projection.z; projection.w = projection.z;
projection.z = tmp; projection.z = tmp;
animate_index = 3;
break; break;
default:
return;
} }
printf("[AXIS] (X,Y,Z,W) = (%d,%d,%d,%d)\n", projection.x, projection.y, projection.z, projection.w); set_projection_mesh(projection);
return; return;
} }
@@ -107,138 +82,80 @@ void __window_callback_input(GLFWwindow *window, int w, int h)
glViewport((w - m) / 2, (h - m) / 2, m, m); glViewport((w - m) / 2, (h - m) / 2, m, m);
} }
static double xpos_s, ypos_s; void __mouse_callback_input(
static char lbutton_down = 0; GLFWwindow *window, int button, int action, int mods)
void __mouse_callback_input(GLFWwindow* window, int button, int action, int mods)
{ {
if( button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) unsigned char green_value;
lbutton_down = 1; double xpos, ypos;
if( button == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) if (button != GLFW_MOUSE_BUTTON_LEFT || action != GLFW_PRESS)
return;
glfwGetCursorPos(window, &xpos, &ypos);
glReadPixels((int)xpos, (int)(window_height - ypos), 1, 1, GL_GREEN,
GL_UNSIGNED_BYTE, &green_value);
switch (green_value)
{ {
glfwGetCursorPos(window, &xpos_s, &ypos_s); case 0xD3:
lbutton_down = 0; case 0xD4:
case 0xD5:
selected_axis = green_value - 0xD3;
} }
}
void __cursor_callback_input(
GLFWwindow *window, double xpos, double ypos)
{
if( lbutton_down )
{
versor p = GLM_QUAT_IDENTITY_INIT;
glm_quatv(p, ANGLE, (vec3){-1*(ypos-ypos_s),(xpos-xpos_s),0});
__input_update_q(p);
}
} }
void __scroll_callback_input(GLFWwindow *window, double xoffset, double yoffset) void __scroll_callback_input(GLFWwindow *window, double xoffset, double yoffset)
{ {
versor p = GLM_QUAT_IDENTITY_INIT; versor p = GLM_QUAT_IDENTITY_INIT;
versor r = GLM_QUAT_IDENTITY_INIT;
// glm_quatv(p, yoffset * ANGLE, axis[selected_axis]); glm_quatv(p, yoffset * ANGLE, axis[selected_axis]);
glm_quatv(p, yoffset * ANGLE * 2, (vec3){-1, 0, 0});
glm_quatv(r, xoffset * ANGLE * 2, (vec3){0, 1, 0});
glm_quat_mul(p, q, q); glm_quat_mul(p, q, q);
glm_quat_mul(r, q, q);
glm_quat_rotatev(p, axis[0], axis[0]); glm_quat_rotatev(p, axis[0], axis[0]);
glm_quat_rotatev(p, axis[1], axis[1]); glm_quat_rotatev(p, axis[1], axis[1]);
glm_quat_rotatev(p, axis[2], axis[2]); glm_quat_rotatev(p, axis[2], axis[2]);
glm_quat_rotatev(r, axis[0], axis[0]);
glm_quat_rotatev(r, axis[1], axis[1]);
glm_quat_rotatev(r, axis[2], axis[2]);
}
void __drop_callback_input(GLFWwindow *window, int count, char **path)
{
struct surface surface;
if (create_surface_klein(*path, &surface))
return;
if (!(projection.mesh = create_mesh(surface)))
return;
projection.m = surface.dim;
set_projection_mesh(projection);
free(surface.norm);
free(surface.data);
} }
quat_t poll_input(window_t window) quat_t poll_input(window_t window)
{ {
versor p = GLM_QUAT_IDENTITY_INIT; versor p = GLM_QUAT_IDENTITY_INIT;
if (glfwGetKey((GLFWwindow *)window, 'W') == GLFW_PRESS) if (glfwGetKey((GLFWwindow *)window, 'Q') == GLFW_PRESS)
{ {
glm_quatv(p, ANGLE, axis[0]); glm_quatv(p, ANGLE, axis[0]);
goto end; goto end;
} }
if (glfwGetKey((GLFWwindow *)window, 'S') == GLFW_PRESS) if (glfwGetKey((GLFWwindow *)window, 'W') == GLFW_PRESS)
{ {
glm_quatv(p, -ANGLE, axis[0]); glm_quatv(p, -ANGLE, axis[0]);
goto end; goto end;
} }
if (glfwGetKey((GLFWwindow *)window, 'A') == GLFW_PRESS) if (glfwGetKey((GLFWwindow *)window, 'A') == GLFW_PRESS)
{
glm_quatv(p, -ANGLE, axis[1]);
goto end;
}
if (glfwGetKey((GLFWwindow *)window, 'D') == GLFW_PRESS)
{ {
glm_quatv(p, ANGLE, axis[1]); glm_quatv(p, ANGLE, axis[1]);
goto end; goto end;
} }
if (glfwGetKey((GLFWwindow *)window, 'Q') == GLFW_PRESS) if (glfwGetKey((GLFWwindow *)window, 'S') == GLFW_PRESS)
{
glm_quatv(p, -ANGLE, axis[1]);
goto end;
}
if (glfwGetKey((GLFWwindow *)window, 'Z') == GLFW_PRESS)
{ {
glm_quatv(p, ANGLE, axis[2]); glm_quatv(p, ANGLE, axis[2]);
goto end; goto end;
} }
if (glfwGetKey((GLFWwindow *)window, 'E') == GLFW_PRESS) if (glfwGetKey((GLFWwindow *)window, 'X') == GLFW_PRESS)
{ {
glm_quatv(p, -ANGLE, axis[2]); glm_quatv(p, -ANGLE, axis[2]);
goto end; goto end;
} }
if (glfwGetKey((GLFWwindow *)window, GLFW_KEY_UP) == GLFW_PRESS)
{
glm_quatv(p, ANGLE, (vec3){1,0,0});
goto end;
}
if (glfwGetKey((GLFWwindow *)window, GLFW_KEY_DOWN) == GLFW_PRESS)
{
glm_quatv(p, -ANGLE, (vec3){1,0,0});
goto end;
}
if (glfwGetKey((GLFWwindow *)window, GLFW_KEY_RIGHT) == GLFW_PRESS)
{
glm_quatv(p, ANGLE, (vec3){0,1,0});
goto end;
}
if (glfwGetKey((GLFWwindow *)window, GLFW_KEY_LEFT) == GLFW_PRESS)
{
glm_quatv(p, -ANGLE, (vec3){0,1,0});
goto end;
}
end: end:
/* glm_quat_mul(p, q, q);
// LOG INFO glm_quat_rotatev(p, axis[0], axis[0]);
if (0) glm_quat_rotatev(p, axis[1], axis[1]);
{ glm_quat_rotatev(p, axis[2], axis[2]);
printf("QUAT: %2.5f %2.5f %2.5f %2.5f\n", q[0], q[1], q[2], q[3]); glm_quat_normalize(q);
printf("\n");
}
*/
__input_update_q(p);
return q; return q;
} }

View File

@@ -1,45 +0,0 @@
#include "main.h"
#include <stdlib.h>
#include <stdio.h>
/*
KLEIN Format:
5 bytes with KLEIN
1 byte empty for scaling
1 byte with the dimention of the surface
8 bytes interprated as an int with the number of vertex
n bytes with the vertex data of the surface
n bytes with the normal data of the surface
where n is the size of the vertex and normal data that could be
calculated as the dimention of the surface time the number of vertes
time the size of a 16 bytes float.
*/
int create_surface_klein(unsigned char *path, struct surface *surface)
{
unsigned long size;
char buffer[5];
FILE *file = fopen(path, "rb");
if (!file)
return 1;
fread(buffer, 1, 5, file);
if (strncmp(buffer, "KLEIN", 5))
return 1;
fread(buffer, 1, 1, file);
fread(&surface->dim, 1, 1, file);
fread(&surface->vertex, 8, 1, file);
size = surface->dim * surface->vertex;
surface->data = malloc(4 * size);
fread(surface->data, 4, size, file);
surface->norm = malloc(4 * size);
fread(surface->norm, 4, size, file);
return 0;
}

View File

@@ -1,34 +0,0 @@
#include "main.h"
#include <cglm/cam.h>
#include <cglm/mat4.h>
#include <cglm/quat.h>
void fix_matrix_load(id_t shader, float ratio)
{
mat4 m, n;
const int d = 7;
glm_lookat((vec3){0, 0, -d}, (vec3){0, 0, 0}, (vec3){0, 1, 0}, m);
glm_perspective(CGLM_PI / 6, ratio, d - 3, d + 3, n);
glm_mat4_mul(n, m, m);
load_mat4_to_shader(shader, "fix", (mat4_t)m);
}
void rot_matrix_load(id_t shader, quat_t q)
{
mat4 m;
glm_quat_mat4(q, m);
load_mat4_to_shader(shader, "rot", (mat4_t)m);
}
void color_load(id_t shader, unsigned char color[4])
{
float res[4];
res[0] = (float)color[0] / 0xff;
res[1] = (float)color[1] / 0xff;
res[2] = (float)color[2] / 0xff;
res[3] = (float)color[3] / 0xff;
load_float4_to_shader(shader, "color", res);
}

View File

@@ -1,4 +1,5 @@
#include "main.h" #include "main.h"
#include "data/axis.h"
#include "data/shaders.h" #include "data/shaders.h"
#include <stdio.h> #include <stdio.h>
@@ -11,33 +12,19 @@
#include <emscripten.h> #include <emscripten.h>
#endif #endif
#ifndef M_PI float *generate_data_surface(unsigned int, unsigned char *);
#define M_PI 3.14159 float *generate_normals_surface(float *, unsigned char);
#endif
struct projection projection = {.x = 0, .y = 1, .z = 2, .w = 3, .mesh = NULL};
const char *wname = "manigraph: manifold grapher"; const char *wname = "manigraph: manifold grapher";
const char *input_map =
"\n"
"DRAG AND DROP: Graph a klein file from the file system\n"
"LEFT-CLICK: Rotate surface on DRAG direction\n"
"SCROLL: Rotate surface on SCROLL direction\n"
"\n"
"W,S: Rotate sufrace on X axis\n"
"A,D: Rotate sufrace on Y axis\n"
"Q,E: Rotate sufrace on Z axis\n"
"LEFT-RIGHT: Rotate sufrace Horizontally\n"
"UP-DOWN: Rotate sufrace Vetrically\n"
"\n"
"Z: Rotate W axis to X axis\n"
"X: Rotate W axis to Y axis\n"
"C: Rotate W axis to Z axis\n"
"1-9: Rotate n axis to W axis\n"
"\n"
;
unsigned char color[4] = {0x2F, 0x3C, 0x7E, 0xff}; struct projection projection = {.x = 0, .y = 1, .z = 2, .w = 3};
unsigned char palette[][4] = {
{0xEB, 0xD3, 0xF8, 0xff},
{0xEB, 0xD4, 0xF8, 0xff},
{0xEB, 0xD5, 0xF8, 0xff},
{0x7A, 0x1C, 0xAC, 0xff},
};
void mlog(char *msg) void mlog(char *msg)
{ {
@@ -47,60 +34,39 @@ void mlog(char *msg)
} }
window_t window; window_t window;
mesh_t m_surface, m_axis;
id_t shader, shader_plain; id_t shader, shader_plain;
extern volatile unsigned char animate_index;
#ifndef EMSCRIPTEN #ifndef EMSCRIPTEN
static inline static inline
#endif #endif
void main_loop(void)
void
main_loop(void)
{ {
quat_t q; quat_t q;
q = poll_input(window); q = poll_input(window);
load_rot_matrix(shader, q);
load_rot_matrix(shader_plain, q);
rot_matrix_load(shader, q);
rot_matrix_load(shader_plain, q);
color_load(shader, color);
color_load(shader_plain, color);
{
static float angle = 0;
if (angle > M_PI / 2)
{
animate_index = 0;
angle = 0;
load_float_to_shader(shader, "angle", angle);
load_float_to_shader(shader_plain, "angle", angle);
set_projection_mesh(projection);
}
if (animate_index)
{
load_float_to_shader(shader, "i", animate_index - 1);
load_float_to_shader(shader_plain, "i", animate_index - 1);
angle += 0.01;
load_float_to_shader(shader, "angle", angle);
load_float_to_shader(shader_plain, "angle", angle);
}
}
clean_context(); clean_context();
if (!projection.mesh) #ifndef DEBUG
return; load_mdl_matrix(shader_plain, 0, 0);
draw_mesh(m_axis);
draw_mesh(shader, projection.mesh); load_mdl_matrix(shader_plain, 1, 1);
draw_mesh_lines(shader_plain, projection.mesh); draw_mesh(m_axis);
load_mdl_matrix(shader_plain, 2, 2);
draw_mesh(m_axis);
load_mdl_matrix(shader, 0, 3);
#else
load_mdl_matrix(shader_plain, 0, 3);
#endif
draw_mesh(m_surface);
} }
int main(void) int main(void)
{ {
id_t texture;
mlog("[VENTANA] Inicializando...\n"); mlog("[VENTANA] Inicializando...\n");
{ {
@@ -120,7 +86,13 @@ int main(void)
mlog("[CONTEXT] Error al inicializar...\n"); mlog("[CONTEXT] Error al inicializar...\n");
goto error_context; goto error_context;
} }
set_clean_color_context(0xFF, 0xFF, 0xFF); set_clean_color_context(0x2E, 0x07, 0x3F);
}
mlog("[TEXTURE] Inicializando...\n");
{
texture = create_palette_texture(palette, 4);
use_texture(texture);
} }
mlog("[SHADER] Inicializando...\n"); mlog("[SHADER] Inicializando...\n");
@@ -132,7 +104,7 @@ int main(void)
} }
load_program_to_shader(shader, vs, VERTEX); load_program_to_shader(shader, vs, VERTEX);
load_program_to_shader(shader, fs, FRAGMENT); load_program_to_shader(shader, fs, FRAGMENT);
fix_matrix_load(shader, (float)WIDTH / HEIGHT); load_fix_matrix(shader, (float)WIDTH / HEIGHT);
} }
mlog("[SHADER] Inicializando...\n"); mlog("[SHADER] Inicializando...\n");
@@ -144,17 +116,42 @@ int main(void)
} }
load_program_to_shader(shader_plain, vs, VERTEX); load_program_to_shader(shader_plain, vs, VERTEX);
load_program_to_shader(shader_plain, fs_plain, FRAGMENT); load_program_to_shader(shader_plain, fs_plain, FRAGMENT);
fix_matrix_load(shader_plain, (float)WIDTH / HEIGHT); load_fix_matrix(shader_plain, (float)WIDTH / HEIGHT);
} }
mlog("[INPUTS] Imprimiendo...\n"); mlog("[MESH] Inicializando...\n");
printf(input_map); {
unsigned char m;
float *n_surface, *d_surface;
d_surface = generate_data_surface(16, &m);
n_surface = generate_normals_surface(d_surface, m);
projection.m = m;
if (!(m_surface = create_mesh(d_surface, n_surface, m)))
{
mlog("[MESH] Error al inicializar...\n");
goto error_mesh_surface;
}
projection.mesh = m_surface;
free(n_surface);
free(d_surface);
}
mlog("[MESH] Inicializando...\n");
{
if (!(m_axis = create_mesh(d_axis, NULL, 3)))
{
mlog("[MESH] Error al inicializar...\n");
goto error_mesh_axis;
}
}
mlog("[MAIN LOOP] Inicializando...\n"); mlog("[MAIN LOOP] Inicializando...\n");
#ifdef EMSCRIPTEN #ifdef EMSCRIPTEN
emscripten_set_main_loop(&main_loop, 60, 1); emscripten_set_main_loop(&main_loop, 0, 1);
return 0;
#else #else
while (is_open_window(window)) while (is_open_window(window))
main_loop(); main_loop();
@@ -162,22 +159,34 @@ int main(void)
mlog("[MAIN LOOP] Terminando...\n"); mlog("[MAIN LOOP] Terminando...\n");
mlog("[MESH] Destruyendo...\n"); mlog("[MESH] Destruyendo...\n");
destroy_mesh(projection.mesh); destroy_mesh(m_axis);
mlog("[MESH] Destruyendo...\n");
destroy_mesh(m_surface);
mlog("[SHADER] Destruyendo...\n"); mlog("[SHADER] Destruyendo...\n");
destroy_shader(shader_plain); destroy_shader(shader_plain);
mlog("[SHADER] Destruyendo...\n"); mlog("[SHADER] Destruyendo...\n");
destroy_shader(shader); destroy_shader(shader);
mlog("[TEXTURE] Destruyendo...\n");
destroy_texture(texture);
mlog("[WINDOW] Destruyendo...\n"); mlog("[WINDOW] Destruyendo...\n");
close_window(window); close_window(window);
return 0; return 0;
error_context: mlog("[MESH] Destruyendo...\n");
destroy_mesh(m_axis);
error_mesh_axis:
mlog("[MESH] Destruyendo...\n");
destroy_mesh(m_surface);
error_mesh_surface:
mlog("[SHADER] Destruyendo...\n"); mlog("[SHADER] Destruyendo...\n");
destroy_shader(shader_plain); destroy_shader(shader_plain);
error_shader_plain: error_shader_plain:
mlog("[SHADER] Destruyendo...\n"); mlog("[SHADER] Destruyendo...\n");
destroy_shader(shader); destroy_shader(shader);
error_shader: error_shader:
mlog("[TEXTURE] Destruyendo...\n");
destroy_texture(texture);
error_context:
mlog("[WINDOW] Destruyendo...\n"); mlog("[WINDOW] Destruyendo...\n");
close_window(window); close_window(window);
error_window: error_window:

View File

@@ -4,15 +4,14 @@
error of the shaders. error of the shaders.
*/ */
#include <stdint.h> /* #define DEBUG */
#define DEBUG /* #define GLAD */
#define GLFW_INCLUDE_NONE
typedef const void *window_t; typedef const void * window_t;
typedef unsigned int id_t; typedef unsigned int id_t;
typedef void *mesh_t; typedef void * mesh_t;
typedef float *quat_t; typedef float * quat_t;
typedef float *mat4_t; typedef float * mat4_t;
/* /*
This struct represent the proyection, where: This struct represent the proyection, where:
@@ -30,22 +29,6 @@ struct projection
unsigned char m, x, y, z, w; unsigned char m, x, y, z, w;
}; };
/*
this structure has all the information to generate
a mesh, where:
data: the buffer with the vertex coords
norm: the buffer with the norm coords
vertex: the number of vertex
dim: the dimentions of the surface
*/
struct surface
{
float *data, *norm;
uint64_t vertex;
uint8_t dim;
};
/* /*
Init window: Init window:
w: default width; w: default width;
@@ -53,9 +36,7 @@ struct surface
name: Name of the window. name: Name of the window.
*/ */
int create_surface_klein( unsigned char *, struct surface * ); window_t init_window(unsigned int w, unsigned int h, const char * name);
window_t init_window(unsigned int w, unsigned int h, const char *name);
void use_window(window_t window); void use_window(window_t window);
@@ -70,15 +51,13 @@ void close_window(window_t window);
m: Dimention of mesh m: Dimention of mesh
*/ */
mesh_t create_mesh(struct surface); mesh_t create_mesh( float * d, float * n, unsigned char m );
void set_projection_mesh(struct projection); void set_projection_mesh( struct projection );
void destroy_mesh(mesh_t p); void destroy_mesh(mesh_t p);
void draw_mesh(id_t, mesh_t p); void draw_mesh(mesh_t p);
void draw_mesh_lines(id_t, mesh_t p);
/* /*
Set background color: Set background color:
@@ -91,7 +70,7 @@ void set_clean_color_context(unsigned char r, unsigned char g, unsigned char b);
void clean_context(void); void clean_context(void);
int init_context(void); int init_context( void );
void destroy_shader(id_t shader); void destroy_shader(id_t shader);
@@ -101,8 +80,7 @@ void use_shader(id_t shader);
enum enum
{ {
VERTEX, VERTEX, FRAGMENT
FRAGMENT
}; };
/* /*
@@ -111,8 +89,7 @@ enum
type: VERTEX or FRAGMENT type: VERTEX or FRAGMENT
*/ */
unsigned char load_program_to_shader( unsigned char load_program_to_shader(id_t shader, const char * src, unsigned int type);
id_t shader, const char *src, unsigned int type);
/* /*
load float to shader: load float to shader:
@@ -120,23 +97,7 @@ unsigned char load_program_to_shader(
f: float to load f: float to load
*/ */
void load_float_to_shader(id_t shader, char *var, float f); void load_float_to_shader(id_t shader, char * var, float f);
/*
load unsigned int to shader:
var: name of glsl variable.
u: unsigned int to load
*/
void load_uint_to_shader(id_t shader, char *var, unsigned int u);
/*
load float[4] to shader:
var: name of glsl variable.
f: float[4] to load
*/
void load_float4_to_shader(id_t shader, char *var, float f[4]);
/* /*
load matrix 4 to shader: load matrix 4 to shader:
@@ -144,7 +105,7 @@ void load_float4_to_shader(id_t shader, char *var, float f[4]);
m: Matrix to load m: Matrix to load
*/ */
void load_mat4_to_shader(id_t shader, char *var, mat4_t m); void load_mat4_to_shader(id_t shader, char * var, mat4_t m);
/* /*
Generate and load fix matrix, this matrix Generate and load fix matrix, this matrix
@@ -153,19 +114,23 @@ void load_mat4_to_shader(id_t shader, char *var, mat4_t m);
ratio: default ratio of window. ratio: default ratio of window.
*/ */
void fix_matrix_load(id_t shader, float ratio); void load_fix_matrix(id_t shader, float ratio);
/*
Generate and load model matrix, it also sets the color
to draw.
i: From {0,1,2} select one of 3 ortogonal rotations,
One for each axis.
c: Color index of the pallete.
*/
void load_mdl_matrix(id_t shader, unsigned char i, unsigned char c);
/* /*
Generate and load rotation matrix. Generate and load rotation matrix.
q: quaterinon describing the rotation. q: quaterinon describing the rotation.
*/ */
void rot_matrix_load(id_t shader, quat_t q); void load_rot_matrix(id_t shader, quat_t q);
/*
*/
void color_load(id_t shader, unsigned char color[4]);
id_t config_texture(unsigned short type); id_t config_texture(unsigned short type);
@@ -178,6 +143,6 @@ void destroy_texture(id_t texture);
colors: array of color values (rgba in hex ). colors: array of color values (rgba in hex ).
n: number of color on colors. n: number of color on colors.
*/ */
id_t create_palette_texture(const unsigned char colors[][4], unsigned char n); id_t create_palette_texture(const unsigned char colors[][4], unsigned char n );
quat_t poll_input(window_t window); quat_t poll_input(window_t window);

50
src/matrix.c Normal file
View File

@@ -0,0 +1,50 @@
#include "main.h"
#include <cglm/cam.h>
#include <cglm/mat4.h>
#include <cglm/quat.h>
mat4 ortho[] = {
{
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1},
},
{
{0, 1, 0, 0},
{-1, 0, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1},
},
{
{0, 0, 1, 0},
{0, 1, 0, 0},
{-1, 0, 0, 0},
{0, 0, 0, 1},
},
};
void load_fix_matrix(id_t shader, float ratio)
{
mat4 m, n;
const int d = 7;
glm_lookat((vec3){0, 0, -d}, (vec3){0, 0, 0}, (vec3){0, 1, 0}, m);
glm_perspective(CGLM_PI / 4, ratio, d - 3, d + 3, n);
glm_mat4_mul(n, m, m);
load_mat4_to_shader(shader, "fix", (mat4_t)m);
}
void load_mdl_matrix(id_t shader, unsigned char i, unsigned char c)
{
load_float_to_shader(shader, "idx", c);
load_mat4_to_shader(shader, "mdl", (mat4_t)ortho[i]);
}
void load_rot_matrix(id_t shader, quat_t q)
{
mat4 m;
glm_quat_mat4(q, m);
load_mat4_to_shader(shader, "rot", (mat4_t)m);
}

View File

@@ -1,11 +1,9 @@
#include "main.h" #include "main.h"
#ifdef GLAD
#ifdef EMSCRIPTEN
#include <GL/gl.h>
#else
#include <glad.h> #include <glad.h>
#else
#include <GL/glew.h>
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -49,34 +47,49 @@ void set_projection_mesh(struct projection projection)
This trick can be done with glVertexAttribPointer. This trick can be done with glVertexAttribPointer.
*/ */
mesh_t create_mesh(struct surface surface) mesh_t create_mesh(float *d, float *n, unsigned char m)
{ {
unsigned char i; unsigned char i;
struct obj *p; struct obj *p;
p = malloc(sizeof(struct obj)); p = malloc(sizeof(struct obj));
p->vertex = surface.vertex; p->vertex = (*d) / m;
glGenVertexArrays(1, &p->vao); glGenVertexArrays(1, &p->vao);
glBindVertexArray(p->vao); glBindVertexArray(p->vao);
glGenBuffers(1, &p->d_vbo); glGenBuffers(1, &p->d_vbo);
glBindBuffer(GL_ARRAY_BUFFER, p->d_vbo); glBindBuffer(GL_ARRAY_BUFFER, p->d_vbo);
glBufferData(GL_ARRAY_BUFFER, p->vertex * surface.dim * sizeof(float), glBufferData(
surface.data, GL_STATIC_DRAW); GL_ARRAY_BUFFER, p->vertex * m * sizeof(float), d + 1, GL_STATIC_DRAW);
if (surface.norm) if (n)
{ {
glGenBuffers(1, &p->n_vbo); glGenBuffers(1, &p->n_vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p->n_vbo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, p->n_vbo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, glBufferData(GL_ELEMENT_ARRAY_BUFFER, p->vertex * m * sizeof(float),
p->vertex * surface.dim * sizeof(float), surface.norm, n + 1, GL_STATIC_DRAW);
GL_STATIC_DRAW);
} }
for (i = 0; i < 8; ++i) for (i = 0; i < 4; ++i)
{
glEnableVertexAttribArray(i); glEnableVertexAttribArray(i);
glEnableVertexAttribArray(i + 4);
}
{
struct projection projection = {
.x = 0,
.y = 1,
.z = 2,
.w = 3,
};
projection.m = m;
projection.mesh = p;
set_projection_mesh(projection);
}
return p; return p;
} }
@@ -91,28 +104,18 @@ void destroy_mesh(mesh_t p)
free(p); free(p);
} }
void draw_mesh(id_t shader, mesh_t p) void draw_mesh(mesh_t p)
{ {
struct obj *obj = p; struct obj *obj = p;
glUseProgram(shader);
glBindVertexArray(obj->vao); glBindVertexArray(obj->vao);
#ifndef EMSCRIPTEN #ifdef DEBUG
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); {
#endif int i;
glDrawArrays(GL_TRIANGLES, 0, obj->vertex); for (i = 0; i < obj->vertex; i += 3)
} glDrawArrays(GL_LINE_LOOP, i, 3);
void draw_mesh_lines(id_t shader, mesh_t p) }
{
struct obj *obj = p;
glLineWidth(4);
glUseProgram(shader);
glBindVertexArray(obj->vao);
#ifndef EMSCRIPTEN
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glDrawArrays(GL_TRIANGLES, 0, obj->vertex);
#else #else
glDrawArrays(GL_LINES, 0, obj->vertex); glDrawArrays(GL_TRIANGLES, 0, obj->vertex);
#endif #endif
} }

View File

@@ -1,20 +1,20 @@
#include "main.h" #include "main.h"
#ifndef EMSCRIPTEN #ifdef GLAD
#include <glad.h> #include <glad.h>
#else #else
#include <GL/gl.h> #include <GL/glew.h>
#endif #endif
#ifdef DEBUG #ifdef DEBUG
#include <stdio.h> #include <stdio.h>
#endif #endif
void destroy_shader(unsigned int shader) { glDeleteProgram(shader); } void destroy_shader(unsigned int shader) { return glDeleteProgram(shader); }
unsigned int create_shader(void) { return glCreateProgram(); } unsigned int create_shader(void) { return glCreateProgram(); }
void use_shader(unsigned int program) { glUseProgram(program); } void use_shader(unsigned int program) { return glUseProgram(program); }
unsigned char load_program_to_shader( unsigned char load_program_to_shader(
unsigned int program, const char *src, unsigned int i) unsigned int program, const char *src, unsigned int i)
@@ -59,10 +59,3 @@ void load_mat4_to_shader(unsigned int program, char *var, float *mat)
glUseProgram(program); glUseProgram(program);
glUniformMatrix4fv(glGetUniformLocation(program, var), 1, 0, mat); glUniformMatrix4fv(glGetUniformLocation(program, var), 1, 0, mat);
} }
void load_float4_to_shader(unsigned int program, char *var, float float4[4])
{
glUseProgram(program);
glUniform4f(glGetUniformLocation(program, var), float4[0], float4[1],
float4[2], float4[3]);
}

234
src/surface.c Normal file
View File

@@ -0,0 +1,234 @@
#include <complex.h>
#include <math.h>
#include <stdlib.h>
#define CGLM_ALL_UNALIGNED
#include <cglm/vec3.h>
#include <cglm/vec4.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef CMPLX
#define CMPLX(a,b) (a+I*b)
#endif
void riemman(float *d_surface, int * coords, int grid_size)
{
complex double eq;
float u = 2 * ((float)coords[0] / grid_size) - 1;
float v = 2 * ((float)coords[1] / grid_size) - 1;
eq = csqrt(CMPLX(u,v));
d_surface[0] = u;
d_surface[1] = v;
d_surface[2] = creal(eq);
d_surface[3] = cimag(eq);
}
void cube( float *d_surface, int * coord, int grid_size )
{
unsigned char i;
for(int i=0; i<4; i++ )
d_surface[i]=(float)coord[i]/grid_size;
}
void mobius(float *d_surface, int * coord, int grid_size)
{
const float width = 0.5;
float u = (2 * M_PI) * ((float)coord[0] / grid_size);
float v = (2 * width) * ((float)coord[1] / grid_size) - width;
d_surface[0] = cos(u) + v * cos(u / 2) * cos(u);
d_surface[1] = sin(u) + v * cos(u / 2) * sin(u);
d_surface[2] = v * sin(u / 2);
}
void torus(float *d_surface, int * coord, int grid_size)
{
float u = (2 * M_PI) * ((float)coord[0] / grid_size);
float v = (2 * M_PI) * ((float)coord[1] / grid_size);
d_surface[0] = (1 + 0.5 * cos(v)) * cos(u);
d_surface[1] = (1 + 0.5 * cos(v)) * sin(u);
d_surface[2] = 0.5 * sin(v);
}
void klein(float *d_surface, int * coord, int grid_size)
{
float u = (2 * M_PI) * ((float)coord[0] / grid_size);
float v = (2 * M_PI) * ((float)coord[1]/ grid_size);
d_surface[0] = (0.5 * cos(v) + 0.5) * cos(u);
d_surface[1] = (0.5 * cos(v) + 0.5) * sin(u);
d_surface[2] = sin(v) * cos(u / 2);
d_surface[3] = sin(v) * sin(u / 2);
}
typedef void (*function_t)(float *, int *, int);
float *generate_data_surface(int grid_size, unsigned char *s)
{
unsigned int i, j, k, o, p, l, n, m;
long size, q=0;
function_t f;
float *d_surface;
const int dim =2;
int cara[dim];
char bits[dim+1];
bits[dim]=0;
f =klein ;
*s = 4;
size = grid_size * grid_size * 6 * (*s) * 24;
d_surface = malloc((size + 1) * sizeof(float));
d_surface[0] = size;
for(o = 0; o < dim; o ++)
{
for (p = 0; p < o; p++)
{
for (k = 0; k < (1 << (dim-2)); k++)
{
unsigned char skip=0;
for(n = 0; n < dim-2; n++)
{
if( n==(o-1) || n==p )
skip++;
cara[n+skip] = (k & (1<<n))?grid_size:0;
}
for(i = 0; i < grid_size; i++)
{
for (j = 0; j < grid_size; j++)
{
cara[o] = i;
cara[p] = j;
f(&d_surface[q + 1], cara, grid_size);
q += *s;
cara[o] = i + 1;
cara[p] = j;
f(&d_surface[q + 1], cara, grid_size);
q += *s;
cara[o] = i + 1;
cara [p] = j + 1;
f(&d_surface[q + 1], cara, grid_size);
q += *s;
cara[o] = i;
cara [p] = j;
f(&d_surface[q + 1], cara, grid_size);
q += *s;
cara[o] = i;
cara [p] = j + 1;
f(&d_surface[q + 1], cara, grid_size);
q += *s;
cara[o] = i + 1;
cara [p] = j + 1;
f(&d_surface[q + 1], cara, grid_size);
q += *s;
}
}
}
}
}
return d_surface;
}
static void __calculate_normal(
float *p1, float *p2, float *p3, float *normal, unsigned char n)
{
float alpha;
vec4 v1, v2, v3;
vec4 u1, u2, u3;
switch (n)
{
case 3:
glm_vec3_sub(p2, p1, v1);
glm_vec3_sub(p3, p1, v2);
glm_vec3_cross(v1, v2, normal);
glm_vec3_normalize(normal);
return;
case 4:
/*
In Grant-Shmidth we need 3 linearly independian vector that forms a
basis, so we can have a ortonormal version of that basis, since, we
must have v1 = p3 - p1 v2 = p2 - p1 Then v3 = p1, will most certantly
be linerly independiant to v1 and v2.
*/
glm_vec4_sub(p2, p1, v1);
glm_vec4_sub(p3, p1, v2);
glm_vec4_copy(p1, v3);
/* Setup U1 */
{
glm_vec4_copy(v1, u1);
}
/* Setup U2 */
{
vec4 proj;
alpha = glm_vec4_dot(v2, u1) / glm_vec4_dot(u1, u1);
glm_vec4_scale(u1, alpha, proj);
glm_vec4_sub(v2, proj, u2);
}
/* Setup U3 */
{
vec4 proj1, proj2;
alpha = glm_vec4_dot(v3, u1) / glm_vec4_dot(u1, u1);
glm_vec4_scale(u1, alpha, proj1);
alpha = glm_vec4_dot(v3, u2) / glm_vec4_dot(u2, u2);
glm_vec4_scale(u2, alpha, proj2);
glm_vec4_sub(v3, proj1, u3);
glm_vec4_sub(u3, proj2, u3);
}
glm_vec4_copy(u3, normal);
glm_vec4_normalize(normal);
return;
}
}
float *generate_normals_surface(float *d, unsigned char m)
{
float *n;
n = malloc((*d + 1) * sizeof(float));
*n = *d;
for (int i = 0; i < *d; i += 3 * m)
{
vec4 norm_vec;
__calculate_normal(
(d + 1) + i, (d + 1) + i + m, (d + 1) + i + 2 * m, norm_vec, m);
glm_vec3_copy(norm_vec, (n + 1) + i);
glm_vec3_copy(norm_vec, (n + 1) + i + m);
glm_vec3_copy(norm_vec, (n + 1) + i + 2 * m);
}
return n;
}

38
src/texture.c Normal file
View File

@@ -0,0 +1,38 @@
#include "main.h"
#ifdef GLAD
#include <glad.h>
#else
#include <GL/glew.h>
#endif
#define TYPE GL_TEXTURE_2D_ARRAY
static id_t __config_texture(unsigned short type)
{
id_t texture;
glGenTextures(1, &texture);
glBindTexture(TYPE, texture);
{
glTexParameteri(TYPE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(TYPE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
return texture;
}
void use_texture(id_t texture) { return glBindTexture(TYPE, texture); }
void destroy_texture(unsigned int texture)
{
return glDeleteTextures(1, &texture);
}
id_t create_palette_texture(const unsigned char colors[][4], unsigned char n)
{
id_t texture = __config_texture(TYPE);
glTexImage3D(
TYPE, 0, GL_RGBA, 1, 1, n, 0, GL_RGBA, GL_UNSIGNED_BYTE, colors);
return texture;
}

View File

@@ -4,12 +4,9 @@
#include <time.h> #include <time.h>
void __window_callback_input(GLFWwindow *, int, int); void __window_callback_input(GLFWwindow *, int, int);
void __cursor_callback_input(GLFWwindow *, double, double);
void __mouse_callback_input(GLFWwindow *, int, int, int); void __mouse_callback_input(GLFWwindow *, int, int, int);
void __scroll_callback_input(GLFWwindow *, double, double); void __scroll_callback_input(GLFWwindow *, double, double);
void __key_callback_input(GLFWwindow *, int, int, int, int); void __key_callback_input(GLFWwindow *, int, int, int, int);
void __drop_callback_input(GLFWwindow *, int, const char **);
void __error_callback_input(int, const char *);
window_t init_window(unsigned int w, unsigned int h, const char *name); window_t init_window(unsigned int w, unsigned int h, const char *name);
@@ -35,12 +32,8 @@ static void __limit_fps_window(int max_fps)
struct timespec sleep_time; struct timespec sleep_time;
sleep_time.tv_sec = 0; sleep_time.tv_sec = 0;
sleep_time.tv_nsec = (long)((frame_time - elapsed_time) * 1e9); sleep_time.tv_nsec = (long)((frame_time - elapsed_time) * 1e9);
#ifdef _WIN32
usleep(sleep_time.tv_nsec/1000);
#else
nanosleep(&sleep_time, NULL); nanosleep(&sleep_time, NULL);
#endif
current_time = glfwGetTime(); current_time = glfwGetTime();
} }
@@ -50,7 +43,6 @@ static void __limit_fps_window(int max_fps)
window_t init_window(unsigned int width, unsigned int height, const char *title) window_t init_window(unsigned int width, unsigned int height, const char *title)
{ {
window_t window; window_t window;
glfwSetErrorCallback(__error_callback_input);
if (!glfwInit()) if (!glfwInit())
return NULL; return NULL;
@@ -58,7 +50,6 @@ window_t init_window(unsigned int width, unsigned int height, const char *title)
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1);
window = (window_t)glfwCreateWindow(width, height, title, NULL, NULL); window = (window_t)glfwCreateWindow(width, height, title, NULL, NULL);
if (!(window)) if (!(window))
@@ -70,11 +61,11 @@ window_t init_window(unsigned int width, unsigned int height, const char *title)
glfwMakeContextCurrent((GLFWwindow *)(window)); glfwMakeContextCurrent((GLFWwindow *)(window));
glfwSetWindowSizeCallback((GLFWwindow *)window, __window_callback_input); glfwSetWindowSizeCallback((GLFWwindow *)window, __window_callback_input);
glfwSetCursorPosCallback((GLFWwindow *)window, __cursor_callback_input);
glfwSetMouseButtonCallback((GLFWwindow *)window, __mouse_callback_input); glfwSetMouseButtonCallback((GLFWwindow *)window, __mouse_callback_input);
glfwSetScrollCallback((GLFWwindow *)window, __scroll_callback_input); glfwSetScrollCallback((GLFWwindow *)window, __scroll_callback_input);
glfwSetKeyCallback((GLFWwindow *)window, __key_callback_input); glfwSetKeyCallback((GLFWwindow *)window, __key_callback_input);
glfwSetDropCallback((GLFWwindow *)window, __drop_callback_input);
__window_callback_input((GLFWwindow *)window, width, height);
return window; return window;
} }