now we are rendering something

This commit is contained in:
TheLastBilly 2022-08-20 13:48:56 -04:00
parent 30f9eca799
commit 56866d523d
16 changed files with 430 additions and 1020 deletions

5
.vscode/launch.json vendored
View File

@ -8,12 +8,11 @@
"name": "(gdb) Launch",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/evwm",
"program": "${workspaceFolder}/debug/evwm",
"args": [],
"stopAtEntry": true,
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": true,
"preLaunchTask":"(Debug) Build",
"MIMode": "gdb",
"setupCommands": [

2
.vscode/tasks.json vendored
View File

@ -7,7 +7,7 @@
{
"label": "(Debug) Build",
"type": "shell",
"command": "make debug"
"command": "make clean && make debug"
},
]
}

View File

@ -11,7 +11,7 @@ CCOBJFLAGS := $(CCFLAGS) -c
# path macros
BIN_PATH := bin
OBJ_PATH := obj
SRC_PATH := ./src
SRC_PATH := src
DBG_PATH := debug
# compile macros

View File

@ -1,14 +1,7 @@
#version 330
in vec2 local_position;
out vec4 fragment_colour;
uniform float opacity;
uniform sampler2D texture_sampler;
void main(void) {
vec4 colour = texture(texture_sampler, local_position * vec2(1.0, -1.0) + vec2(0.5));
float alpha = opacity * (1.0 - colour.a);
fragment_colour = vec4(colour.rgb, alpha);
fragment_colour = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}

View File

@ -1,13 +1,11 @@
#version 330
layout(location = 0) in vec2 vertex_position;
out vec2 local_position;
layout(location = 0) in vec3 vertex_position;
uniform float depth;
uniform vec2 position;
uniform vec2 size;
uniform vec2 window_position;
void main(void) {
local_position = vertex_position;
gl_Position = vec4(vertex_position * size + position, depth, 1.0);
vec3 final_position = vertex_position + vec3(window_position, 0.0);
gl_Position = vec4(final_position.x, final_position.y, final_position.z, 1.0);
}

BIN
research/render_triangle Executable file

Binary file not shown.

View File

@ -0,0 +1,198 @@
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);
// settings
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
const char *vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
"}\0";
const char *fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main()\n"
"{\n"
" FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";
int main()
{
// glfw: initialize and configure
// ------------------------------
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
// glfw window creation
// --------------------
GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// glad: load all OpenGL function pointers
// ---------------------------------------
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
return -1;
}
// build and compile our shader program
// ------------------------------------
// vertex shader
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
// check for shader compile errors
int success;
char infoLog[512];
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// fragment shader
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
// check for shader compile errors
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
}
// link shaders
unsigned int shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
// check for linking errors
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// set up vertex data (and buffer(s)) and configure vertex attributes
// ------------------------------------------------------------------
float vertices[] = {
0.5f, 0.5f, 0.0f, // top right
0.5f, -0.5f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f // top left
};
unsigned int indices[] = { // note that we start from 0!
0, 1, 3, // first Triangle
1, 2, 3 // second Triangle
};
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
// bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind
glBindBuffer(GL_ARRAY_BUFFER, 0);
// remember: do NOT unbind the EBO while a VAO is active as the bound element buffer object IS stored in the VAO; keep the EBO bound.
//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
// You can unbind the VAO afterwards so other VAO calls won't accidentally modify this VAO, but this rarely happens. Modifying other
// VAOs requires a call to glBindVertexArray anyways so we generally don't unbind VAOs (nor VBOs) when it's not directly necessary.
glBindVertexArray(0);
// uncomment this call to draw in wireframe polygons.
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// render loop
// -----------
while (!glfwWindowShouldClose(window))
{
// input
// -----
processInput(window);
// render
// ------
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// draw our first triangle
glUseProgram(shaderProgram);
glBindVertexArray(VAO); // seeing as we only have a single VAO there's no need to bind it every time, but we'll do so to keep things a bit more organized
//glDrawArrays(GL_TRIANGLES, 0, 6);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// glBindVertexArray(0); // no need to unbind it every time
// glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
// -------------------------------------------------------------------------------
glfwSwapBuffers(window);
glfwPollEvents();
}
// optional: de-allocate all resources once they've outlived their purpose:
// ------------------------------------------------------------------------
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &EBO);
glDeleteProgram(shaderProgram);
// glfw: terminate, clearing all previously allocated GLFW resources.
// ------------------------------------------------------------------
glfwTerminate();
return 0;
}
// process all input: query GLFW whether relevant keys are pressed/released this frame and react accordingly
// ---------------------------------------------------------------------------------------------------------
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
// glfw: whenever the window size changed (by OS or user resize) this callback function executes
// ---------------------------------------------------------------------------------------------
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
// make sure the viewport matches the new window dimensions; note that width and
// height will be significantly larger than specified on retina displays.
glViewport(0, 0, width, height);
}

344
src/cm.c
View File

@ -18,23 +18,13 @@ typedef void (*glXBindTexImageEXT_t) (Display*, GLXDrawable, int,
typedef void (*glXReleaseTexImageEXT_t) (Display*, GLXDrawable, int);
typedef void (*glXSwapIntervalEXT_t) (Display*, GLXDrawable, int);
typedef struct vao_vbo_ibo_t
{
GLuint vao, vbo, ibo;
} vao_vbo_ibo_t;
typedef struct window_vertices_t
{
float vertices[4 * 2];
} window_vertices_t;
static const char * MAIN_SHADER_UNIFORM_NAMES[] = {
"opacity",
"texture_sampler",
"depth",
"position",
"size",
"window_position"
};
typedef struct main_shader_t
@ -43,21 +33,16 @@ typedef struct main_shader_t
struct
{
int opacity;
int texture_sampler;
int depth;
int position;
int size;
int window_position;
} uniforms;
} main_shader_t;
typedef struct window_extra_t
{
bool drawable;
Pixmap xpixmap;
GLXPixmap pixmap;
vao_vbo_ibo_t buffers;
} window_extra_t;
typedef struct cm_t
@ -67,7 +52,8 @@ typedef struct cm_t
Display* display;
Window root_window;
XWindowAttributes root_window_attributes;
XWindowAttributes root_window_attributes,
output_window_attributes;
Window check_window, overlay_window,
output_window;
@ -86,11 +72,15 @@ typedef struct cm_t
glXSwapIntervalEXT_t glXSwapIntervalEXT;
main_shader_t main_shader;
bool allocated_buffer;
unsigned int vbo, vao, ebo;
} cm_t;
static cm_t cm = {0};
static const int DEFAULT_GLX_VISUAL_ATTRIBUTES[] = {
static const int
DEFAULT_GLX_VISUAL_ATTRIBUTES[] = {
GLX_RGBA, GLX_DOUBLEBUFFER,
GLX_SAMPLE_BUFFERS, 1,
GLX_SAMPLES, 4,
@ -103,7 +93,8 @@ static const int DEFAULT_GLX_VISUAL_ATTRIBUTES[] = {
0
};
static const int DEFAULT_GLX_FB_ATTRIBUTES[] = {
static const int
DEFAULT_GLX_FB_ATTRIBUTES[] = {
GLX_BIND_TO_TEXTURE_RGBA_EXT, 1,
GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
@ -125,7 +116,8 @@ static const int DEFAULT_GLX_FB_ATTRIBUTES[] = {
0
};
static const int DEFAULT_GLX_VERSION_ATTRIBUTES[] = {
static const int
DEFAULT_GLX_VERSION_ATTRIBUTES[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
@ -133,6 +125,35 @@ static const int DEFAULT_GLX_VERSION_ATTRIBUTES[] = {
0
};
static const unsigned int
WINDOW_INDICES[] = {
0, 1, 3,
1, 2, 3,
};
static inline bool
should_render_window( window_node_t * node )
{
return (
node->window != cm.check_window &&
node->window != cm.overlay_window &&
node->window != cm.output_window &&
node->window != cm.root_window
);
}
static void
free_window_pixmap(window_extra_t *extra)
{
if (extra->xpixmap)
XFreePixmap(cm.display, extra->xpixmap);
if (extra->pixmap)
glXDestroyPixmap(cm.display, extra->pixmap);
extra->xpixmap = extra->pixmap = 0;
}
static void
create_window_pixmap( window_node_t * window_node )
{
@ -147,7 +168,12 @@ create_window_pixmap( window_node_t * window_node )
0
};
extra = (window_extra_t *)window_node->extra;
if(extra->pixmap)
return;
XGetWindowAttributes(cm.display, window_node->window, &window_node->attributes);
for (int i = 0; i < cm.fb_config_count; i++) {
config = cm.fb_config[i];
@ -163,88 +189,19 @@ create_window_pixmap( window_node_t * window_node )
format = has_alpha ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT;
break;
}
extra = (window_extra_t *)window_node->extra;
pixmap_attributes[3] = format;
extra->xpixmap = XCompositeNameWindowPixmap(cm.display, window_node->window);
extra->pixmap = glXCreatePixmap(cm.display, config, extra->xpixmap, (const int *)pixmap_attributes);
}
static vao_vbo_ibo_t
create_vao_vbo_ibo( void )
{
vao_vbo_ibo_t buffers;
glGenVertexArrays(1, &buffers.vao);
glGenBuffers(1, &buffers.vbo);
glGenBuffers(1, &buffers.ibo);
return buffers;
}
static void
free_vao_vbo_ibo( vao_vbo_ibo_t buffers )
{
glDeleteBuffers(1, &buffers.ibo);
glDeleteBuffers(1, &buffers.vbo);
glDeleteVertexArrays(1, &buffers.vao);
clear(&buffers);
}
static void
get_window_vertices(window_node_t * node, window_vertices_t * vertices)
{
float half_width = 0.0f, half_height = 0.0f;
half_width = node->attributes.width / cm.root_window_attributes.width;
half_height = node->attributes.height / cm.root_window_attributes.height;
int v[] = {
-half_width, half_height,
half_width, half_height,
half_width, -half_height,
-half_width, -half_height,
};
memcpy(&vertices->vertices, v, sizeof(v));
}
static int
update_window_buffers( window_node_t * window_node )
{
window_extra_t * extra = NULL;
window_vertices_t vertices = {0};
static const int indices[] = {
3, 0, 1,
1, 2, 3
};
extra = (window_extra_t *)window_node->extra;
get_window_vertices(window_node, &vertices);
glBindVertexArray(extra->buffers.vao);
glBindBuffer(GL_ARRAY_BUFFER, extra->buffers.vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices.vertices), vertices.vertices,
GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, extra->buffers.ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
return 0;
}
static inline window_extra_t *
create_window_extra( window_node_t * node )
{
window_extra_t * extra = NULL;
extra = gcalloc(1, sizeof(window_extra_t));
extra->buffers = create_vao_vbo_ibo();
create_window_pixmap(node);
update_window_buffers(node);
node->extra = extra;
return extra;
}
@ -323,25 +280,17 @@ compile_shaders( void )
return 0;
}
static void
free_window_pixmap(window_extra_t *extra)
{
if (extra->xpixmap)
XFreePixmap(cm.display, extra->xpixmap);
if (extra->pixmap)
glXDestroyPixmap(cm.display, extra->pixmap);
}
static int
bind_window_texture( window_node_t * window_node )
{
window_extra_t * extra = NULL;
extra = create_window_extra_if_none(window_node);
extra = window_node->extra;
if(!extra || !extra->drawable)
return 0;
cm.glXBindTexImageEXT(cm.display, extra->pixmap, GLX_FRONT_LEFT_EXT,
NULL);
create_window_pixmap(window_node);
cm.glXBindTexImageEXT(cm.display, extra->pixmap, GLX_FRONT_LEFT_EXT, NULL);
return 0;
}
@ -351,46 +300,100 @@ unbind_window_texture( window_node_t * window_node )
{
window_extra_t * extra = NULL;
extra = create_window_extra_if_none(window_node);
extra = window_node->extra;
if(!extra || !extra->drawable)
return 0;
if(extra->pixmap)
cm.glXReleaseTexImageEXT(cm.display, extra->pixmap, GLX_FRONT_LEFT_EXT);
return 0;
}
static int
render_window( window_node_t * window_node )
int
cm_swap_buffers( void )
{
window_extra_t * extra = NULL;
extra = create_window_extra_if_none(window_node);
glUseProgram(cm.main_shader.program);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE0);
glUniform1i(cm.main_shader.uniforms.texture_sampler, 0);
bind_window_texture(window_node);
glBindVertexArray(extra->buffers.vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, NULL);
unbind_window_texture(window_node);
glXSwapBuffers(cm.display, cm.output_window);
return 0;
}
int
cm_render_windows( void )
static int
render_window( window_node_t * window_node )
{
int ret = 0;
float h_height = 0.0f, h_width = 0.0f, x = 0, y = 0;
window_extra_t * extra = NULL;
extra = create_window_extra_if_none(window_node);
if(!extra->drawable)
return 0;
XGetWindowAttributes(cm.display, cm.output_window, &cm.output_window_attributes);
XGetWindowAttributes(cm.display, window_node->window, &window_node->attributes);
h_height = (float)window_node->attributes.height / (float)cm.output_window_attributes.height;
h_width = (float)window_node->attributes.width / (float)cm.output_window_attributes.width;
x = (float)(window_node->attributes.x - window_node->attributes.width/2)/(float)cm.output_window_attributes.width;
y = -(float)(window_node->attributes.y - window_node->attributes.height/2)/(float)cm.output_window_attributes.height;
float vertices[] = {
h_width, h_height, 0.0f,
h_width, -h_height, 0.0f,
-h_width, -h_height, 0.0f,
-h_width, h_height, 0.0f,
};
bind_window_texture(window_node);
glBindVertexArray(cm.vao);
glBindBuffer(GL_ARRAY_BUFFER, cm.vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cm.ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(WINDOW_INDICES), WINDOW_INDICES, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glUseProgram(cm.main_shader.program);
glUniform2f(cm.main_shader.uniforms.window_position, x, y);
glBindVertexArray(cm.vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
unbind_window_texture(window_node);
return ret;
}
int
cm_render_windows(void)
{
window_node_t * node = NULL;
glClearColor(0.16015625, 0.15625, 0.15625, 1.);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
XGrabServer(cm.display);
node = wm_get_first_window_node();
while(node)
{
if(should_render_window(node))
render_window(node);
node = node->next;
}
cm_swap_buffers();
XUngrabServer(cm.display);
return 0;
}
@ -406,8 +409,6 @@ free_window_extra(window_node_t * node)
free_window_pixmap(extra);
gfree(extra);
extra = NULL;
free_vao_vbo_ibo(extra->buffers);
}
}
@ -418,7 +419,7 @@ on_create_window(window_node_t * node)
free_window_extra(node->extra);
create_window_extra(node);
render_window(node);
((window_extra_t *)node->extra)->drawable = true;
}
static void
@ -439,9 +440,7 @@ cm_init( unsigned int modkey )
clear(&cm);
callbacks.on_create_window = on_create_window;
callbacks.on_destroy_window = on_destroy_window;
err = wm_init(modkey, &callbacks);
err = wm_init(modkey);
if(err)
ftl("cannot initialize window manager");
@ -453,42 +452,37 @@ cm_init( unsigned int modkey )
// Make it known to other apps that you are a compositing window
// manager
cm.check_window = XCreateSimpleWindow(cm.display, cm.root_window,
0, 0, 1, 1, 0, 0, 0);
Xutf8SetWMProperties(cm.display, cm.check_window, XCOMPMGR_PROPERTY,
XCOMPMGR_PROPERTY, NULL, 0, NULL, NULL, NULL);
cm.check_window = XCreateSimpleWindow(cm.display, cm.root_window, 0, 0, 1, 1, 0, 0, 0);
Xutf8SetWMProperties(cm.display, cm.check_window, XCOMPMGR_PROPERTY, XCOMPMGR_PROPERTY,
NULL, 0, NULL, NULL, NULL);
snprintf(net_wm_cm, sizeof(net_wm_cm), "_NET_WM_CM_S%d", cm.screen);
cm.net_wm_cm_atom = XInternAtom(cm.display, net_wm_cm, 0);
XSetSelectionOwner(cm.display, cm.net_wm_cm_atom, cm.check_window, 0);
XCompositeRedirectSubwindows(cm.display, cm.root_window, CompositeRedirectAutomatic);
XCompositeRedirectSubwindows(cm.display, cm.root_window, CompositeRedirectManual);
// We use this so we can make windows transparents to events
cm.overlay_window = XCompositeGetOverlayWindow(cm.display, cm.root_window);
region = XFixesCreateRegion(cm.display, NULL, 0);
XFixesSetWindowShapeRegion(cm.display, cm.overlay_window, ShapeInput,
0, 0, region);
XFixesSetWindowShapeRegion(cm.display, cm.overlay_window, ShapeInput, 0, 0, region);
XFixesDestroyRegion(cm.display, region);
// Create the window where we will be drawing on
cm.default_visual = glXChooseVisual(cm.display, cm.screen,
(int *)DEFAULT_GLX_VISUAL_ATTRIBUTES);
cm.default_visual = glXChooseVisual(cm.display, cm.screen, (int *)DEFAULT_GLX_VISUAL_ATTRIBUTES);
if(!cm.default_visual)
ftl("cannot get default glx visual");
default_visual_attributes = (XSetWindowAttributes){
.colormap = XCreateColormap(cm.display, cm.root_window, cm.default_visual->visual,
AllocNone)
};
.colormap = XCreateColormap(cm.display, cm.root_window, cm.default_visual->visual, AllocNone),
.border_pixel = 0};
// Get root window attributes for the output window
wm_get_window_attributes(cm.root_window, &window_attrbiutes);
cm.output_window = XCreateWindow(cm.display, cm.root_window, 0, 0,
window_attrbiutes.width, window_attrbiutes.height, 0, cm.default_visual->depth,
InputOutput, cm.default_visual->visual, CWBorderPixel | CWColormap,
&default_visual_attributes);
cm.output_window = XCreateWindow(cm.display, cm.root_window, 0, 0, window_attrbiutes.width,
window_attrbiutes.height, 0, cm.default_visual->depth, InputOutput, cm.default_visual->visual,
CWBorderPixel | CWColormap, &default_visual_attributes);
XReparentWindow(cm.display, cm.output_window, cm.overlay_window, 0, 0);
XMapRaised(cm.display, cm.output_window);
@ -500,15 +494,13 @@ cm_init( unsigned int modkey )
ftl("cannot get glx framebuffer configs");
// Get OpenGL function callbacks
cm.glXCreateContextAttribsARB = (glXCreateContextAttribsARB_t) glXGetProcAddressARB(
(const GLubyte*) "glXCreateContextAttribsARB");
cm.glXBindTexImageEXT = (glXBindTexImageEXT_t) glXGetProcAddress((const GLubyte*) "glXBindTexImageEXT");
cm.glXReleaseTexImageEXT = (glXReleaseTexImageEXT_t) glXGetProcAddress((const GLubyte*) "glXReleaseTexImageEXT");
cm.glXSwapIntervalEXT = (glXSwapIntervalEXT_t) glXGetProcAddress((const GLubyte*) "glXSwapIntervalEXT");
cm.glXCreateContextAttribsARB = (glXCreateContextAttribsARB_t) glXGetProcAddressARB( (const GLubyte*) "glXCreateContextAttribsARB");
cm.glXBindTexImageEXT = (glXBindTexImageEXT_t) glXGetProcAddress((const GLubyte*) "glXBindTexImageEXT");
cm.glXReleaseTexImageEXT = (glXReleaseTexImageEXT_t) glXGetProcAddress((const GLubyte*) "glXReleaseTexImageEXT");
cm.glXSwapIntervalEXT = (glXSwapIntervalEXT_t) glXGetProcAddress((const GLubyte*) "glXSwapIntervalEXT");
// Create OpenGL context
cm.glx_context = cm.glXCreateContextAttribsARB(cm.display, cm.fb_config[0], NULL, 1,
DEFAULT_GLX_VERSION_ATTRIBUTES);
cm.glx_context = cm.glXCreateContextAttribsARB(cm.display, cm.fb_config[0], NULL, 1, DEFAULT_GLX_VERSION_ATTRIBUTES);
if(!cm.glx_context)
ftl("cannot create OpenGL context");
@ -516,6 +508,7 @@ cm_init( unsigned int modkey )
glXMakeCurrent(cm.display, cm.output_window, cm.glx_context);
// Initialize GLEW
glewExperimental = GL_TRUE;
if(glewInit() != GLEW_OK)
ftl("cannot initialize GLEW");
@ -525,6 +518,20 @@ cm_init( unsigned int modkey )
ftl("cannot compile shaders")
inf("done compiling shaders");
callbacks.on_create_window = on_create_window;
callbacks.on_destroy_window = on_destroy_window;
wm_set_callbacks(callbacks);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glGenVertexArrays(1, &cm.vao);
glGenBuffers(1, &cm.vbo);
glGenBuffers(1, &cm.ebo);
cm.allocated_buffer = true;
return 0;
}
@ -545,6 +552,13 @@ cm_destroy( void )
if(cm.main_shader.program)
glDeleteProgram(cm.main_shader.program);
if(cm.allocated_buffer)
{
glDeleteVertexArrays(1, &cm.vao);
glDeleteBuffers(1, &cm.vbo);
glDeleteBuffers(1, &cm.ebo);
}
wm_destroy();
clear(&cm);

View File

@ -13,6 +13,8 @@
int cm_init( unsigned int modkey );
int cm_destroy( void );
int cm_swap_buffers( void );
int cm_render_windows( void );
#endif

View File

@ -1,690 +0,0 @@
#include <stdio.h>
#include "util.h"
#include "geometry.h"
#include "fmath.h"
// Debug functions I use to display the contents of
// some structures. No need to pay much attention to
// these tho
const char*
matrix_to_str(matrix_t m)
{
static char buff[1024] = {0};
snprintf(buff, 1024,
"[%f]\t[%f]\t[%f]\t[%f]\n"
"[%f]\t[%f]\t[%f]\t[%f]\n"
"[%f]\t[%f]\t[%f]\t[%f]\n"
"[%f]\t[%f]\t[%f]\t[%f]",
m[0][0], m[0][1], m[0][2], m[0][3],
m[1][0], m[1][1], m[1][2], m[1][3],
m[2][0], m[2][1], m[2][2], m[2][3],
m[3][0], m[3][1], m[3][2], m[3][3]
);
return buff;
}
const char*
column_to_str(column_t c)
{
static char buff[1024] = {0};
snprintf(buff, 1024,
"c[0][0] = %f, c[1][0] = %f, c[2][0] = %f, c[3][0] = %f",
c[0][0],c[1][0],c[2][0],c[3][0]
);
return buff;
}
const char*
pv_to_str(struct pv_t *p)
{
static char buff[1024] = {0};
snprintf(buff, 1024,
"p->x = %f, p->y = %f, p->z = %f, p->w = %f",
p->x, p->y, p->z, p->w
);
return buff;
}
// Copy the contents of matrix d to s
void
copy_matrix(matrix_t s, matrix_t d)
{
int r = 0;
for(r = 0; r < 4; r++)
{
d[r][0] = s[r][0];
d[r][1] = s[r][1];
d[r][2] = s[r][2];
d[r][3] = s[r][3];
}
}
// Sets all the contents of a matrix to 0.0
void
clear_matrix(matrix_t m)
{
matrix_t b = {{0.0}};
copy_matrix(b, m);
}
// r = a - b
void
substract_pv(struct pv_t *a, struct pv_t *b, struct pv_t *r)
{
r->x = a->x - b->x;
r->y = a->y - b->y;
r->z = a->z - b->z;
r->w = 0.0;
}
// Returns a + b
void
add_pv(struct pv_t *a, struct pv_t *b, struct pv_t *r)
{
r->x = a->x + b->x;
r->y = a->y + b->y;
r->z = a->z + b->z;
r->w = 0.0;
}
// r = p * s
void
scale_pv(struct pv_t * p, float s, struct pv_t *r)
{
r->x = p->x * s;
r->y = p->y * s;
r->z = p->z * s;
}
// r = p / s
void
divide_pv(struct pv_t *p, float s, struct pv_t *r)
{
scale_pv(p, 1.0/s, r);
}
// r = a * b
void
multiply_pv(struct pv_t *a, struct pv_t *b, struct pv_t *r)
{
r->x = a->x * b->x;
r->y = a->y * b->y;
r->z = a->z * b->z;
}
// Returns ||v||
float
magnitude_pv(struct pv_t *v)
{
return sqrtf(pow2((v)->x) + pow2((v)->y) + pow2((v)->z));
}
// r = v/(||v||)
void
normalize_pv(struct pv_t *v, struct pv_t *r)
{
float m = 0.0;
m = magnitude_pv(v);
r->x = v->x/m;
r->y = v->y/m;
r->z = v->z/m;
}
// r = 1/p
// Returns the inverse of p.
// I had to get a little experimental with this, so I hope
// it works. Essentially this will check if any of the
// components on the vector is equal to 0, and if they are,
// the resulting value on r will be equal to INFINITY
void inverse_pv(struct pv_t* p, struct pv_t *r)
{
#define csign(x) (((x) >= 0) - ((x) < 0))
r->x = (p->x == 0 ? csign(p->x) * INFINITY : 1.0/p->x);
r->y = (p->y == 0 ? csign(p->y) * INFINITY : 1.0/p->y);
r->z = (p->z == 0 ? csign(p->z) * INFINITY : 1.0/p->z);
#undef csgin
}
float
dot_product(struct pv_t *a, struct pv_t *b)
{
return a->x * b->x + a->y * b->y + a->z * b->z;
}
void
cross_pv(struct pv_t *a, struct pv_t *b, struct pv_t *r)
{
r->x = a->y * b->z - a->z * b->y;
r->y = a->z * b->x - a->x * b->z;
r->z = a->x * b->y - a->y * b->x;
}
// Okay, so everyone seems to
// Checks if pointvector is a point
// Just in case I need to add other criteria to this
// later
static inline bool
is_point(struct pv_t *p)
{
return p->w > 0;
}
// Converts a pv_t to a column_t
static inline void
pv_to_column(struct pv_t *p, column_t c)
{
c[0][0] = p->x;
c[1][0] = p->y;
c[2][0] = p->z;
c[3][0] = p->w;
}
// Converts a column_t to a pv_t
static inline void
column_to_pv(column_t c, struct pv_t *p)
{
p->x = c[0][0];
p->y = c[1][0];
p->z = c[2][0];
p->w = c[3][0];
}
// Yeah... I don't have time to worry about
// how to calculate the inverse of a matrix.
// Like, I know how to do this, but I was spending
// too much time writing my own method so f*ck it,
// I asked San Google for some help with this one.
//
// Taken from
// https://stackoverflow.com/questions/1148309/inverting-a-4x4-matrix
// (I would have referenced the original source for the function
// but I couldn't find it)
//
// Also, I made this inlined since it's only going to be used
// in one place. So essentially, this would be the same as
// wiriting this function on inv_matrix, but I wanted to separate
// this from inv_matrix since I didn't write this myself.
inline static bool
_inv_matrix(const float m[16], float r[16])
{
float inv[16], det;
int i;
inv[0] =
m[5] * m[10] * m[15] -
m[5] * m[11] * m[14] -
m[9] * m[6] * m[15] +
m[9] * m[7] * m[14] +
m[13] * m[6] * m[11] -
m[13] * m[7] * m[10];
inv[4] =
-m[4] * m[10] * m[15] +
m[4] * m[11] * m[14] +
m[8] * m[6] * m[15] -
m[8] * m[7] * m[14] -
m[12] * m[6] * m[11] +
m[12] * m[7] * m[10];
inv[8] =
m[4] * m[9] * m[15] -
m[4] * m[11] * m[13] -
m[8] * m[5] * m[15] +
m[8] * m[7] * m[13] +
m[12] * m[5] * m[11] -
m[12] * m[7] * m[9];
inv[12] =
-m[4] * m[9] * m[14] +
m[4] * m[10] * m[13] +
m[8] * m[5] * m[14] -
m[8] * m[6] * m[13] -
m[12] * m[5] * m[10] +
m[12] * m[6] * m[9];
inv[1] =
-m[1] * m[10] * m[15] +
m[1] * m[11] * m[14] +
m[9] * m[2] * m[15] -
m[9] * m[3] * m[14] -
m[13] * m[2] * m[11] +
m[13] * m[3] * m[10];
inv[5] =
m[0] * m[10] * m[15] -
m[0] * m[11] * m[14] -
m[8] * m[2] * m[15] +
m[8] * m[3] * m[14] +
m[12] * m[2] * m[11] -
m[12] * m[3] * m[10];
inv[9] =
-m[0] * m[9] * m[15] +
m[0] * m[11] * m[13] +
m[8] * m[1] * m[15] -
m[8] * m[3] * m[13] -
m[12] * m[1] * m[11] +
m[12] * m[3] * m[9];
inv[13] =
m[0] * m[9] * m[14] -
m[0] * m[10] * m[13] -
m[8] * m[1] * m[14] +
m[8] * m[2] * m[13] +
m[12] * m[1] * m[10] -
m[12] * m[2] * m[9];
inv[2] =
m[1] * m[6] * m[15] -
m[1] * m[7] * m[14] -
m[5] * m[2] * m[15] +
m[5] * m[3] * m[14] +
m[13] * m[2] * m[7] -
m[13] * m[3] * m[6];
inv[6] =
-m[0] * m[6] * m[15] +
m[0] * m[7] * m[14] +
m[4] * m[2] * m[15] -
m[4] * m[3] * m[14] -
m[12] * m[2] * m[7] +
m[12] * m[3] * m[6];
inv[10] =
m[0] * m[5] * m[15] -
m[0] * m[7] * m[13] -
m[4] * m[1] * m[15] +
m[4] * m[3] * m[13] +
m[12] * m[1] * m[7] -
m[12] * m[3] * m[5];
inv[14] =
-m[0] * m[5] * m[14] +
m[0] * m[6] * m[13] +
m[4] * m[1] * m[14] -
m[4] * m[2] * m[13] -
m[12] * m[1] * m[6] +
m[12] * m[2] * m[5];
inv[3] =
-m[1] * m[6] * m[11] +
m[1] * m[7] * m[10] +
m[5] * m[2] * m[11] -
m[5] * m[3] * m[10] -
m[9] * m[2] * m[7] +
m[9] * m[3] * m[6];
inv[7] =
m[0] * m[6] * m[11] -
m[0] * m[7] * m[10] -
m[4] * m[2] * m[11] +
m[4] * m[3] * m[10] +
m[8] * m[2] * m[7] -
m[8] * m[3] * m[6];
inv[11] =
-m[0] * m[5] * m[11] +
m[0] * m[7] * m[9] +
m[4] * m[1] * m[11] -
m[4] * m[3] * m[9] -
m[8] * m[1] * m[7] +
m[8] * m[3] * m[5];
inv[15] =
m[0] * m[5] * m[10] -
m[0] * m[6] * m[9] -
m[4] * m[1] * m[10] +
m[4] * m[2] * m[9] +
m[8] * m[1] * m[6] -
m[8] * m[2] * m[5];
det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];
if (det == 0)
return false;
det = 1.0 / det;
for (i = 0; i < 16; i++)
r[i] = inv[i] * det;
return true;
}
// r = inv(m)
// If m doesn't have an inverse, then inv_matrix
// will act just like copy_matrix
void
inv_matrix(matrix_t m, matrix_t r)
{
bool s;
s = _inv_matrix((const float *)m, (float *)r);
if(s)
return;
else
copy_matrix(m, r);
}
// r = m * x
// Matrix times column operation. Do not use
// c as r as well. This will cause problems
void
mxc(matrix_t m, column_t c, column_t r)
{
r[0][0] = m[0][0] * c[0][0] + m[0][1] * c[1][0] + m[0][2] * c[2][0] + m[0][3] * c[3][0];
r[1][0] = m[1][0] * c[0][0] + m[1][1] * c[1][0] + m[1][2] * c[2][0] + m[1][3] * c[3][0];
r[2][0] = m[2][0] * c[0][0] + m[2][1] * c[1][0] + m[2][2] * c[2][0] + m[2][3] * c[3][0];
r[3][0] = m[3][0] * c[0][0] + m[3][1] * c[1][0] + m[3][2] * c[2][0] + m[3][3] * c[3][0];
}
// r = m * c
// Matrix times column operation. Do not use
// c as r as well. This will cause problems
void
mxm(matrix_t m, matrix_t c, matrix_t r)
{
unsigned char i = 0;
// I know I didn't NEED to use a loop here, but this is due in
// a week
for(i = 0; i < 4; i++)
{
r[0][i] = m[0][0] * c[0][i] + m[0][1] * c[1][i] + m[0][2] * c[2][i] + m[0][3] * c[3][i];
r[1][i] = m[1][0] * c[0][i] + m[1][1] * c[1][i] + m[1][2] * c[2][i] + m[1][3] * c[3][i];
r[2][i] = m[2][0] * c[0][i] + m[2][1] * c[1][i] + m[2][2] * c[2][i] + m[2][3] * c[3][i];
r[3][i] = m[3][0] * c[0][i] + m[3][1] * c[1][i] + m[3][2] * c[2][i] + m[3][3] * c[3][i];
}
}
// m = Im
void
make_identity_matrix(matrix_t m)
{
m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0;
m[0][1] = m[0][2] = m[0][3] =
m[1][0] = m[1][2] = m[1][3] =
m[2][0] = m[2][1] = m[2][3] =
m[3][0] = m[3][1] = m[3][2] = 0.0;
}
// m = T(x, y, z)
void
make_translation_matrix(float x, float y, float z, matrix_t m)
{
m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0;
m[0][3] = x;
m[1][3] = y;
m[2][3] = z;
m[0][1] = 0.0;
m[0][2] = 0.0;
m[1][0] = 0.0;
m[1][2] = 0.0;
m[2][0] = 0.0;
m[2][1] = 0.0;
m[3][0] = 0.0;
m[3][1] = 0.0;
m[3][2] = 0.0;
}
// m = S(x, y, z)
void
make_scaling_matrix(float x, float y, float z, matrix_t m)
{
m[0][0] = x;
m[1][1] = y;
m[2][2] = z;
m[3][3] = 1.0;
m[0][1] = 0.0;
m[0][2] = 0.0;
m[0][3] = 0.0;
m[1][0] = 0.0;
m[1][2] = 0.0;
m[1][3] = 0.0;
m[2][0] = 0.0;
m[2][1] = 0.0;
m[2][3] = 0.0;
m[3][0] = 0.0;
m[3][1] = 0.0;
m[3][2] = 0.0;
}
// m = R(t, u)
// t => Thetha: Angle for the rotation
// u => Unit Vector: Normal vector indicating the rotation axis(es)
void
make_rotation_matrix(float t, struct pv_t *u, matrix_t m)
{
float x2 = .0, y2 = .0, z2 = .0, sint = .0, cost = .0, d = .0;
x2 = pow2(u->x);
y2 = pow2(u->y);
z2 = pow2(u->z);
d = deg2rad(t);
cost = cos(d);
sint = sin(d);
m[0][0] = x2 + cost*(1-x2);
m[0][1] = u->x * u->y * (1-cost) - u->z*sint;
m[0][2] = u->x * u->z * (1-cost) + u->y*sint;
m[0][3] = 0.0;
m[1][0] = u->x * u->y * (1-cost) + u->z*sint;
m[1][1] = y2 + cost*(1-y2);
m[1][2] = u->y * u->z * (1-cost) - u->x*sint;
m[1][3] = 0.0;
m[2][0] = u->x * u->z * (1-cost) - u->y*sint;
m[2][1] = u->y * u->z * (1-cost) + u->x*sint;
m[2][2] = z2 + cost*(1-z2);
m[2][3] = 0.0;
m[3][0] = 0.0;
m[3][1] = 0.0;
m[3][2] = 0.0;
m[3][3] = 1.0;
}
// Apply transform matrix m to pv
void
transform_pv(matrix_t m, struct pv_t *p, struct pv_t *r)
{
column_t a, c;
pv_to_column(p, c);
mxc(m, c, a);
column_to_pv(a, r);
}
// Multiply m by all the pv_t on src and save
// the results on dst
void
transform_pv_arr(matrix_t m, struct pv_t *src, struct pv_t *dst, size_t s)
{
column_t a, c;
while(s > 0)
{
s--;
pv_to_column(&src[s], c);
mxc(m, c, a);
column_to_pv(a, &dst[s]);
}
}
// Reflects i around normal n
void
reflect_pv(struct pv_t *i, struct pv_t *n, struct pv_t *r)
{
struct pv_t p = {0.0};
scale_pv(n, dot_product(i, n) * 2.0, &p);
substract_pv(i, &p, r);
}
void
make_sphere(struct pv_t *center, float radius, struct sphere_t *s)
{
s->radius = radius;
s->radius2 = pow2(radius);
s->center = *center;
s->type = GEOMETRY_SPHERE;
s->param = NULL;
}
void
make_plane(struct pv_t *center, struct pv_t *normal, struct plane_t * plane)
{
plane->center = *center;
plane->normal = *normal;
plane->type = GEOMETRY_PLANE;
}
void
make_triangle(struct pv_t *a, struct pv_t *b, struct pv_t *c, struct triangle_t *t)
{
// I know I could have used ac instead... but
// I also want to be able to understand this in
// the future
struct pv_t ca, cp;
t->edges[0] = *a;
t->edges[1] = *b;
t->edges[2] = *c;
// Use for intersection check
substract_pv(b, a, &t->ba);
substract_pv(c,b, &t->cb);
substract_pv(a,c, &t->ac);
substract_pv(c, a, &ca);
cross_pv(&t->ba, &ca, &cp);
normalize_pv(&cp, &t->normal);
t->area = dot_product(&cp, &t->normal);
t->type = GEOMETRY_TRIANGLE;
}
void
transform_triangle(struct triangle_t *t, matrix_t m, struct triangle_t *r)
{
transform_pv(m, &t->edges[0], &t->edges[0]);
transform_pv(m, &t->edges[1], &t->edges[1]);
transform_pv(m, &t->edges[2], &t->edges[2]);
make_triangle(&t->edges[0], &t->edges[1], &t->edges[2], r);
}
void
new_mesh(struct mesh_t *m, size_t c)
{
matrix_t i;
m->triangles = (struct triangle_t *)calloc(c, sizeof(struct triangle_t));
m->triangle_count = c;
make_identity_matrix(i);
copy_matrix(i, m->transform);
copy_matrix(i, m->inv_transform);
}
void
free_mesh(struct mesh_t *m)
{
if(m->triangles != NULL)
free(m->triangles);
m->triangles = NULL;
m->triangle_count = 0;
}
void
transform_mesh(struct mesh_t *m, matrix_t t, struct mesh_t *r)
{
size_t i = 0;
matrix_t b;
for(; i < m->triangle_count; i++)
transform_triangle(&m->triangles[i], t, &r->triangles[i]);
mxm(t, m->transform, b);
inv_matrix(b, r->inv_transform);
copy_matrix(b, r->transform);
}
void transform_object(struct gobject_t *g, matrix_t t, struct gobject_t *r)
{
switch (g->type)
{
case GEOMETRY_SPHERE:
transform_pv(t, &g->center, &r->center);
break;
case GEOMETRY_TRIANGLE:
transform_triangle(g, t, r);
default:
break;
}
}
void
new_rectangle_mesh(struct pv_t *a, struct pv_t *b, struct pv_t *c, struct pv_t *d, struct mesh_t *m)
{
new_mesh(m, 2);
make_triangle(a, b, c, &m->triangles[0]);
make_triangle(c, d, a, &m->triangles[1]);
m->triangles[0].single_sided = m->triangles[1].single_sided = false;
m->has_bounding_sphere = true;
// substract_pv(b, a, &p);
// radius = magnitude_pv(&p)/2;
// normalize_pv(&p, &p);
// scale_pv(&p, radius, &p);
// add_pv(a, &p, &p);
// make_sphere(&p, radius, &m->bounding_sphere);
}
void
new_rectangle_mesh_wh(float width, float height, struct mesh_t *m)
{
struct pv_t a, b, c;
a = b = c = PV(0.0, 0.0, 0.0);
new_mesh(m, 2);
a.x = width;
c.z = -height;
make_triangle(&b, &a, &c, &m->triangles[0]);
b.z = c.z;
b.x = a.x;
make_triangle(&a, &b, &c, &m->triangles[1]);
m->triangles[0].single_sided = m->triangles[1].single_sided = false;
}

View File

@ -1,135 +0,0 @@
#ifndef GEOMETRY_H__
#define GEOMETRY_H__
#include <math.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#ifndef M_PI
#define M_PI ((double)3.14159265358979323846)
#endif
// // Returns p^2
// // Because p*p takes too long to write
// #define pow2(p) (p)*(p)
// Converts angle from degrees to radiants
#define deg2rad(t) ((t * M_PI)/180.0)
#define PV(a, b, c) (struct pv_t){.x = a, .y = b, .z = c, .w = 1.0}
#define SPHERE(v, r) (struct gobject_t){.type = GEOMETRY_SPHERE, .center = v, .radius = r, .radius2 = pow2(r)}
#define DISK(c, n, r) (struct gobject_t){.type = GEOMETRY_DISK, .center = c, .normal = n, .radius = r, .radius2 = pow2(r)}
#define PLANE(c, n) (struct gobject_t){.type = GEOMETRY_PLANE, .center = c, .normal = n}
#define TRIANGLE(a, b, c, n) (struct gobject_t){.type = GEOMETRY_TRIANGLE, .edges[0] = a, .edges[1] = b, .edges[2] = c, .normal = n}
#define MIN(a,b) (((a)<(b))?(a):(b))
#define MAX(a,b) (((a)>(b))?(a):(b))
typedef uint32_t pixel_t;
typedef float matrix_t[4][4];
typedef float column_t[4][1];
struct pv_t
{ float x,y,z,w; };
enum gobject_type_t
{
GEOMETRY_TRIANGLE,
GEOMETRY_SPHERE,
GEOMETRY_PLANE,
GEOMETRY_DISK,
};
struct gobject_t
{
enum gobject_type_t type;
struct pv_t center;
bool emitter;
struct pv_t normal;
union
{
struct
{
float radius;
float radius2;
};
struct
{
struct pv_t edges[3], ba, cb, ac;
bool single_sided;
float area;
};
};
void *param;
};
#define triangle_t gobject_t
#define sphere_t gobject_t
#define plane_t gobject_t
struct mesh_t
{
struct triangle_t *triangles;
size_t triangle_count;
matrix_t transform, inv_transform;
struct gobject_t bounding_sphere;
bool has_bounding_sphere;
};
const char* matrix_to_str(matrix_t m);
const char* column_to_str(column_t c);
const char* pv_to_str(struct pv_t *p);
void copy_matrix(matrix_t s, matrix_t d);
void clear_matrix(matrix_t m);
float magnitude_pv(struct pv_t *v);
void reflect_pv(struct pv_t *i, struct pv_t *n, struct pv_t *r);
void substract_pv(struct pv_t *a, struct pv_t *b, struct pv_t *r);
void add_pv(struct pv_t *a, struct pv_t *b, struct pv_t *r);
void scale_pv(struct pv_t * p, float s, struct pv_t *r);
void divide_pv(struct pv_t *p, float s, struct pv_t *r);
void multiply_pv(struct pv_t *a, struct pv_t *b, struct pv_t *r);
void normalize_pv(struct pv_t *v, struct pv_t *r);
void inverse_pv(struct pv_t* p, struct pv_t *r);
void cross_pv(struct pv_t *a, struct pv_t *b, struct pv_t *r);
float dot_product(struct pv_t *a, struct pv_t *b);
void inv_matrix(matrix_t m, matrix_t r);
void mxc(matrix_t m, column_t c, column_t r);
void mxm(matrix_t m, matrix_t c, matrix_t r);
void make_identity_matrix(matrix_t m);
void make_translation_matrix(float x, float y, float z, matrix_t m);
void make_scaling_matrix(float x, float y, float z, matrix_t m);
void make_rotation_matrix(float t, struct pv_t *u, matrix_t m);
void transform_pv(matrix_t m, struct pv_t *p, struct pv_t *r);
void transform_pv_arr(matrix_t m, struct pv_t *src, struct pv_t *dst, size_t s);
void make_triangle(struct pv_t *a, struct pv_t *b, struct pv_t *c, struct triangle_t *t);
void transform_triangle(struct triangle_t *t, matrix_t m, struct triangle_t *r);
void make_sphere(struct pv_t *center, float radius, struct sphere_t *s);
void make_plane(struct pv_t *center, struct pv_t *normal, struct plane_t * plane);
void new_mesh(struct mesh_t *m, size_t c);
void free_mesh(struct mesh_t *m);
void transform_object(struct gobject_t *g, matrix_t t, struct gobject_t *r);
void transform_mesh(struct mesh_t *m, matrix_t t, struct mesh_t *r);
void new_rectangle_mesh(struct pv_t *a, struct pv_t *b, struct pv_t *c, struct pv_t *d, struct mesh_t *m);
void new_rectangle_mesh_wh(float width, float height, struct mesh_t *m);
#endif

View File

@ -6,12 +6,20 @@
int
main(int argc, char const *argv[])
{
uint64_t next_update = 0;
gmema_init();
cm_init(Mod1Mask);
while(!wm_process_events())
;
{
if(time_ms() >= next_update)
{
next_update = time_ms() + 25;
cm_render_windows();
cm_swap_buffers();
}
}
cm_destroy();
return 0;

View File

@ -10,18 +10,20 @@ GLint error_log_lenght = 0;
int
shader_compile(GLuint shader, const char * source, const char * err[])
{
int ret = 0;
gmema_init();
glShaderSource(shader, 1, &source, 0);
glCompileShader(shader);
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &error_log_lenght);
glGetShaderiv(shader, GL_COMPILE_STATUS, &ret);
if(error_log_buffer)
gfree(error_log_buffer);
error_log_buffer = gmalloc(sizeof(*error_log_buffer) * error_log_lenght);
if(error_log_lenght)
if(error_log_lenght || ret == GL_FALSE)
{
glGetShaderInfoLog(shader, error_log_lenght, NULL, error_log_buffer);
if(err)

View File

@ -1,6 +1,7 @@
#ifndef __UTIL_H__
#define __UTIL_H__
#include <sys/time.h>
#include <errno.h>
#include <stdio.h>
#include <stdbool.h>
@ -39,6 +40,13 @@
typedef unsigned int uint;
#endif
static inline uint64_t
time_ms(void)
{
struct timeval current_time = {0};
gettimeofday(&current_time, 0);
return current_time.tv_sec*1000 + current_time.tv_usec/1000;
}
static inline int
read_file(const char * file_path, char ** data, size_t *size)

View File

@ -10,6 +10,10 @@
#define XERROR_MSG_LEN 255
#ifndef XDISPLAY_NAME
#define XDISPLAY_NAME ":4.0"
#endif
typedef struct active_window_t
{
bool defined;
@ -305,7 +309,14 @@ wm_kill_window( Window window )
}
int
wm_init(unsigned int modkey, wm_callbacks_t * callbacks)
wm_set_callbacks( wm_callbacks_t callbacks )
{
wm.callbacks = callbacks;
return 0;
}
int
wm_init(unsigned int modkey)
{
unused(wm_display_error);
@ -313,10 +324,7 @@ wm_init(unsigned int modkey, wm_callbacks_t * callbacks)
clear(&wm);
if(callbacks)
wm.callbacks = *callbacks;
if((wm.display = XOpenDisplay(NULL)) == NULL)
if((wm.display = XOpenDisplay(XDISPLAY_NAME)) == NULL)
ftl("cannot open X11 display");
// Setup X11 error handler
@ -426,7 +434,7 @@ wm_move_window( Window window, int x, int y )
err = XMoveWindow(wm.display, window, x, y);
// dbg("window (%ld) moved to (%d, %d)", window, x, y);
dbg("window (%ld) moved to (%d, %d)", window, x, y);
return err;
}
@ -499,9 +507,12 @@ wm_process_events()
}
window = x_get_event_window(event);
if(window == wm.root_window)
return 0;
if(window)
node = find_window(window);
switch(event.type)
{
case CreateNotify:

View File

@ -27,9 +27,11 @@ typedef struct wm_callbacks_t
void (*on_create_window)(window_node_t * node);
} wm_callbacks_t;
int wm_init( unsigned int modkey, wm_callbacks_t *callbacks );
int wm_init( unsigned int modkey );
int wm_destroy( void );
int wm_set_callbacks( wm_callbacks_t callbacks );
int wm_get_screen( void );
Display * wm_get_display( void );
Window wm_get_root_window( void );