Compare commits
No commits in common. "2a0ed92cfc4a393459fe64d4223b2a06bee2ebc5" and "c2c11a6aba517880a4a97302be43cc7b59e70da6" have entirely different histories.
2a0ed92cfc
...
c2c11a6aba
11
Makefile
11
Makefile
|
@ -1,4 +1,4 @@
|
|||
.PHONY: run clean install all gl_test
|
||||
.PHONY: run clean install all
|
||||
.DELETE_ON_ERROR: $(BINDIR)/Getting_Started_with_GTK
|
||||
.DEFAULT_GOAL: all
|
||||
|
||||
|
@ -20,15 +20,6 @@ SOURCES = $(shell find $(SRCDIR) -type f -name "*.c")
|
|||
OBJECTS = $(patsubst %.c,$(BUILDDIR)/%.o,$(SOURCES))
|
||||
DEPENDENCIES = $(patsubst %.c,$(BUILDDIR)/%.d,$(SOURCES))
|
||||
|
||||
sandbox: opengl_sandbox/main.c
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) $(WARNINGS) $(DEBUG)-o $@ $<
|
||||
|
||||
gl_run: sandbox
|
||||
./$<
|
||||
|
||||
gl_clean:
|
||||
rm sandbox
|
||||
|
||||
all: $(BINDIR)/gem-graph-client
|
||||
|
||||
-include /etc/os-release
|
||||
|
|
Binary file not shown.
|
@ -6,17 +6,15 @@
|
|||
#include <gtk/gtk.h> // GTK types
|
||||
|
||||
|
||||
// General declaration zone ---------------------------------------------------
|
||||
|
||||
#define N_INSTANCE 5
|
||||
#define N_SPACE_SIZE 20
|
||||
|
||||
GtkWidget *window;
|
||||
|
||||
// OpenGL objects
|
||||
GLuint vao, arrow_vao;
|
||||
GLuint vbo, arrow_vbo, cubes_instance_vbo, arrow_instance_vbo;
|
||||
GLuint ebo, arrow_ebo, edge_ebo;
|
||||
GLuint vao, vbo, ebo, instance_vbo, arrow_instance_vbo;
|
||||
GLuint arrow_vao, arrow_vbo, arrow_ebo;
|
||||
GLuint edge_ebo;
|
||||
GLuint shader_program;
|
||||
unsigned int num_instances = N_INSTANCE;
|
||||
mat4 instance_matrices[N_INSTANCE];
|
||||
|
@ -36,12 +34,12 @@ static bool rotate;
|
|||
// Projection and view matrices
|
||||
mat4 projection, view;
|
||||
|
||||
// Function Prototypes zone ---------------------------------------------------
|
||||
|
||||
// Function Prototypes
|
||||
GLuint create_shader_program ();
|
||||
void setup_cubes_buffers ();
|
||||
void setup_buffers ();
|
||||
void setup_arrow_buffers ();
|
||||
void setup_cube_instance_data ();
|
||||
void setup_instance_data ();
|
||||
void setup_arrow_instance_data();
|
||||
static void on_realize (GtkGLArea *area);
|
||||
static gboolean on_render (GtkGLArea *area, GdkGLContext *context);
|
||||
|
@ -49,10 +47,7 @@ static void on_activate (GtkApplication *app, gpointer user_data);
|
|||
static gboolean on_mouse_scroll(GtkEventControllerScroll *controller, gdouble dx, gdouble dy, gpointer user_data);
|
||||
static gboolean on_mouse_move(GtkEventControllerMotion *controller, gdouble x, gdouble y, gpointer user_data);
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Vertex and fragment shader source code
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
const char *vertex_shader_src = "#version 460 core\n"
|
||||
"layout (location = 0) in vec3 aPos;\n"
|
||||
"layout (location = 2) in mat4 instanceMatrix;\n"
|
||||
|
@ -69,10 +64,7 @@ const char *fragment_shader_src = "#version 460 core\n"
|
|||
" finalColor = vec4(FragColor.rgb, 0.3); // Set alpha to 30%\n"
|
||||
"}\n";
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Vertices and indices
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Cube vertices and indices
|
||||
GLfloat vertices[] = {
|
||||
-0.5f, -0.5f, -0.5f, // 0
|
||||
0.5f, -0.5f, -0.5f, // 1
|
||||
|
@ -132,10 +124,6 @@ GLuint arrow_indices[] = {
|
|||
0, 6 // Center to Back face
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// MOUSE MANAGEMENT ZONE
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Maps a 2D point on the screen to a 3D point on a virtual trackball (sphere)
|
||||
void trackball_map(float x, float y, int width, int height, vec3 out)
|
||||
{
|
||||
|
@ -204,6 +192,7 @@ static gboolean on_mouse_move(GtkEventControllerMotion *controller, gdouble x, g
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean on_mouse_scroll(GtkEventControllerScroll *controller, gdouble dx, gdouble dy, gpointer user_data)
|
||||
{
|
||||
if (dy > 0)
|
||||
|
@ -226,294 +215,7 @@ static gboolean on_mouse_scroll(GtkEventControllerScroll *controller, gdouble dx
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// OpenGL zone
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Create the shader program
|
||||
GLuint create_shader_program ()
|
||||
{
|
||||
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex_shader, 1, &vertex_shader_src, NULL);
|
||||
glCompileShader(vertex_shader);
|
||||
|
||||
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment_shader, 1, &fragment_shader_src, NULL);
|
||||
glCompileShader(fragment_shader);
|
||||
|
||||
GLuint program = glCreateProgram();
|
||||
glAttachShader(program, vertex_shader);
|
||||
glAttachShader(program, fragment_shader);
|
||||
glLinkProgram(program);
|
||||
|
||||
glDeleteShader(vertex_shader);
|
||||
glDeleteShader(fragment_shader);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
// Setup OpenGL buffers (VBO, VAO, EBO for cubes and edges)
|
||||
void setup_cubes_buffers ()
|
||||
{
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
// Vertex buffer
|
||||
glGenBuffers(1, &vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
// Face Index buffer (EBO for cube faces)
|
||||
glGenBuffers(1, &ebo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||
|
||||
// Vertex attributes
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
// Edge Index buffer (EBO for cube edges)
|
||||
glGenBuffers(1, &edge_ebo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, edge_ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(edge_indices), edge_indices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
// Setup instance data for cubes (random positions)
|
||||
void setup_cube_instance_data ()
|
||||
{
|
||||
g_message("[%s] setting up cube instance data...",
|
||||
__func__);
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
g_message("[%s] random seed initialized",
|
||||
__func__);
|
||||
|
||||
glGenBuffers(1, &cubes_instance_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubes_instance_vbo);
|
||||
|
||||
g_message("[%s] cubes_instance_vbo buffer bound",
|
||||
__func__);
|
||||
|
||||
for (unsigned int i = 0; i < num_instances; i++) {
|
||||
glm_mat4_identity(instance_matrices[i]);
|
||||
|
||||
// Randomize positions
|
||||
vec3 position = {
|
||||
(float)(rand() % N_SPACE_SIZE) - 10.0f, // Random x from -10 to 10
|
||||
(float)(rand() % N_SPACE_SIZE) - 10.0f, // Random y from -10 to 10
|
||||
(float)(rand() % N_SPACE_SIZE) - 10.0f // Random z from -10 to 10
|
||||
};
|
||||
|
||||
glm_translate(instance_matrices[i], position);
|
||||
}
|
||||
|
||||
g_message("[%s] generated %d cube instances",
|
||||
__func__,
|
||||
num_instances);
|
||||
|
||||
// Pass the instance matrices to the instance VBO
|
||||
glBufferData(GL_ARRAY_BUFFER, num_instances * sizeof(mat4), instance_matrices, GL_STATIC_DRAW);
|
||||
|
||||
g_message("[%s] instance matrices passed to VBO",
|
||||
__func__);
|
||||
|
||||
// Setup vertex attribute for the model matrix (location = 2)
|
||||
// Setup vertex attribute for the model matrix (location = 2)
|
||||
glBindVertexArray(vao);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glVertexAttribPointer(2 + i, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (void*)(sizeof(vec4) * i));
|
||||
glEnableVertexAttribArray(2 + i);
|
||||
glVertexAttribDivisor(2 + i, 1); // Tell OpenGL this is per-instance data
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
g_message("[%s] finalized model matrix vertex attribute ",
|
||||
__func__);
|
||||
}
|
||||
|
||||
void setup_arrow_buffers()
|
||||
{
|
||||
glGenVertexArrays(1, &arrow_vao);
|
||||
glBindVertexArray(arrow_vao);
|
||||
|
||||
// Vertex buffer for arrows
|
||||
glGenBuffers(1, &arrow_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, arrow_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(arrow_vertices), arrow_vertices, GL_STATIC_DRAW);
|
||||
|
||||
// Index buffer for arrows
|
||||
glGenBuffers(1, &arrow_ebo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrow_ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(arrow_indices), arrow_indices, GL_STATIC_DRAW);
|
||||
|
||||
// Vertex attributes
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void setup_arrow_instance_data()
|
||||
{
|
||||
// Define indices for the arrows (lines from center to cube faces)
|
||||
GLuint arrow_indices[] = {
|
||||
0, 1, // Arrow pointing to right face
|
||||
0, 2, // Arrow pointing upwards
|
||||
0, 3, // Arrow pointing to front face
|
||||
0, 4, // Arrow pointing to left face
|
||||
0, 5, // Arrow pointing downwards
|
||||
0, 6 // Arrow pointing to back face
|
||||
};
|
||||
|
||||
// Generate Vertex Buffer Object for arrows
|
||||
glGenBuffers(1, &arrow_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, arrow_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(arrow_vertices), arrow_vertices, GL_STATIC_DRAW);
|
||||
|
||||
// Generate Element Buffer Object for arrows
|
||||
glGenBuffers(1, &arrow_ebo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrow_ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(arrow_indices), arrow_indices, GL_STATIC_DRAW);
|
||||
|
||||
// Define arrow vertex attributes
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
// Arrow instance matrices (positions) -- same as cubes
|
||||
glGenBuffers(1, &arrow_instance_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, arrow_instance_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, num_instances * sizeof(mat4), instance_matrices, GL_STATIC_DRAW);
|
||||
|
||||
// Define vertex attribute for arrow instance matrix
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glVertexAttribPointer(2 + i, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (void*)(sizeof(vec4) * i));
|
||||
glEnableVertexAttribArray(2 + i);
|
||||
glVertexAttribDivisor(2 + i, 1); // Make this per-instance data
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// GTK / OpenGL zone
|
||||
// ----------------------------------------------------------------------------
|
||||
// Called when GtkGLArea is realized (OpenGL context is created)
|
||||
static void on_realize(GtkGLArea *area)
|
||||
{
|
||||
g_message("[%s] GLArea realization in progress...", __func__);
|
||||
|
||||
gtk_gl_area_make_current(GTK_GL_AREA(area));
|
||||
|
||||
g_message("[%s] GLArea made current", __func__);
|
||||
|
||||
if (gtk_gl_area_get_error(GTK_GL_AREA(area)) != NULL) return;
|
||||
|
||||
g_message("[%s] OpenGL context successfully created", __func__);
|
||||
|
||||
// Enable depth testing
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
// Initialize cglm projection and view matrices
|
||||
glm_mat4_identity(projection);
|
||||
glm_perspective(glm_rad(60.0f), 800.0f / 600.0f, 0.1f, 100.0f, projection);
|
||||
|
||||
glm_mat4_identity(view);
|
||||
glm_lookat((vec3){0.0f, 0.0f, 20.0f}, (vec3){0.0f, 0.0f, 0.0f}, (vec3){0.0f, 1.0f, 0.0f}, view);
|
||||
|
||||
// Initialize rotation matrix
|
||||
glm_mat4_identity(rotation_matrix); // Initialize to identity
|
||||
|
||||
// Create shader program and setup buffers
|
||||
shader_program = create_shader_program();
|
||||
setup_cubes_buffers();
|
||||
setup_arrow_buffers();
|
||||
setup_cube_instance_data();
|
||||
setup_arrow_instance_data(); // Setup arrow data
|
||||
|
||||
// Set the background color
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Dark gray background
|
||||
glLineWidth(2.0f); // Increase the line width for cube edges
|
||||
}
|
||||
|
||||
|
||||
// Called on each frame to render the scene
|
||||
static gboolean on_render(GtkGLArea *area, GdkGLContext *context)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
glUseProgram(shader_program);
|
||||
|
||||
// Pass projection and view matrices to the shader
|
||||
GLint projectionLoc = glGetUniformLocation(shader_program, "projection");
|
||||
GLint viewLoc = glGetUniformLocation(shader_program, "view");
|
||||
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, (const GLfloat *)projection);
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, (const GLfloat *)view);
|
||||
|
||||
// Update instance matrices with the accumulated rotation matrix
|
||||
if (rotate) {
|
||||
for (unsigned int i = 0; i < num_instances; i++) {
|
||||
mat4 model;
|
||||
glm_mat4_copy(rotation_matrix, model); // Copy the accumulated rotation matrix
|
||||
|
||||
// Combine the rotation with the instance's individual matrix
|
||||
glm_mul(model, instance_matrices[i], instance_matrices[i]);
|
||||
}
|
||||
rotate = FALSE;
|
||||
}
|
||||
|
||||
// Update the instance matrix buffer with the modified instance matrices
|
||||
glBindBuffer(GL_ARRAY_BUFFER, cubes_instance_vbo);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, num_instances * sizeof(mat4), instance_matrices);
|
||||
|
||||
// Draw the cubes with the updated instance matrices
|
||||
glUniform4f(glGetUniformLocation(shader_program, "FragColor"), 0.4f, 0.6f, 0.9f, 1.0f);
|
||||
glBindVertexArray(vao);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0, num_instances);
|
||||
|
||||
// Draw the cube edges
|
||||
glUniform4f(glGetUniformLocation(shader_program, "FragColor"), 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, edge_ebo);
|
||||
glDrawElementsInstanced(GL_LINES, 24, GL_UNSIGNED_INT, 0, num_instances);
|
||||
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
// Set arrow color (e.g., red) and draw arrows
|
||||
glUniform4f(glGetUniformLocation(shader_program, "FragColor"), 1.0f, 0.0f, 0.0f, 1.0f); // Red, opaque
|
||||
|
||||
// Bind the arrow VAO and use the same transformation matrices
|
||||
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, (const GLfloat *)projection);
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, (const GLfloat *)view);
|
||||
|
||||
// Draw the arrows
|
||||
glBindVertexArray(arrow_vao);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrow_ebo);
|
||||
glDrawElementsInstanced(GL_LINES, 12, GL_UNSIGNED_INT, 0, num_instances);
|
||||
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Reset the rotation matrix to prevent continuous accumulation
|
||||
glm_mat4_identity(rotation_matrix);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// GTK ZONE
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Called when GtkApplication is activated
|
||||
static void on_activate (GtkApplication *app, gpointer user_data)
|
||||
|
@ -561,6 +263,280 @@ static void on_activate (GtkApplication *app, gpointer user_data)
|
|||
__func__);
|
||||
}
|
||||
|
||||
// Called when GtkGLArea is realized (OpenGL context is created)
|
||||
static void on_realize(GtkGLArea *area)
|
||||
{
|
||||
g_message("[%s] GLArea realization in progress...", __func__);
|
||||
|
||||
gtk_gl_area_make_current(GTK_GL_AREA(area));
|
||||
|
||||
g_message("[%s] GLArea made current", __func__);
|
||||
|
||||
if (gtk_gl_area_get_error(GTK_GL_AREA(area)) != NULL) return;
|
||||
|
||||
g_message("[%s] OpenGL context successfully created", __func__);
|
||||
|
||||
// Enable depth testing
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
// Initialize cglm projection and view matrices
|
||||
glm_mat4_identity(projection);
|
||||
glm_perspective(glm_rad(60.0f), 800.0f / 600.0f, 0.1f, 100.0f, projection);
|
||||
|
||||
glm_mat4_identity(view);
|
||||
glm_lookat((vec3){0.0f, 0.0f, 20.0f}, (vec3){0.0f, 0.0f, 0.0f}, (vec3){0.0f, 1.0f, 0.0f}, view);
|
||||
|
||||
// Initialize rotation matrix
|
||||
glm_mat4_identity(rotation_matrix); // Initialize to identity
|
||||
|
||||
// Create shader program and setup buffers
|
||||
shader_program = create_shader_program();
|
||||
setup_buffers();
|
||||
setup_arrow_buffers();
|
||||
setup_instance_data();
|
||||
setup_arrow_instance_data(); // Setup arrow data
|
||||
|
||||
// Set the background color
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Dark gray background
|
||||
glLineWidth(2.0f); // Increase the line width for cube edges
|
||||
}
|
||||
|
||||
|
||||
// Called on each frame to render the scene
|
||||
static gboolean on_render(GtkGLArea *area, GdkGLContext *context)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
glUseProgram(shader_program);
|
||||
|
||||
// Pass projection and view matrices to the shader
|
||||
GLint projectionLoc = glGetUniformLocation(shader_program, "projection");
|
||||
GLint viewLoc = glGetUniformLocation(shader_program, "view");
|
||||
glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, (const GLfloat *)projection);
|
||||
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, (const GLfloat *)view);
|
||||
|
||||
// Update instance matrices with the accumulated rotation matrix
|
||||
if (rotate) {
|
||||
for (unsigned int i = 0; i < num_instances; i++) {
|
||||
mat4 model;
|
||||
glm_mat4_copy(rotation_matrix, model); // Copy the accumulated rotation matrix
|
||||
|
||||
// Combine the rotation with the instance's individual matrix
|
||||
glm_mul(model, instance_matrices[i], instance_matrices[i]);
|
||||
}
|
||||
rotate = FALSE;
|
||||
}
|
||||
|
||||
// Update the instance matrix buffer with the modified instance matrices
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, num_instances * sizeof(mat4), instance_matrices);
|
||||
|
||||
// Draw the cubes with the updated instance matrices
|
||||
glUniform4f(glGetUniformLocation(shader_program, "FragColor"), 0.4f, 0.6f, 0.9f, 1.0f);
|
||||
glBindVertexArray(vao);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
glDrawElementsInstanced(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0, num_instances);
|
||||
|
||||
// Draw the cube edges
|
||||
glUniform4f(glGetUniformLocation(shader_program, "FragColor"), 1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, edge_ebo);
|
||||
glDrawElementsInstanced(GL_LINES, 24, GL_UNSIGNED_INT, 0, num_instances);
|
||||
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
// Set arrow color (e.g., red) and draw arrows
|
||||
glUniform4f(glGetUniformLocation(shader_program, "FragColor"), 1.0f, 0.0f, 0.0f, 1.0f); // Red, opaque
|
||||
glBindVertexArray(arrow_vao);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrow_ebo);
|
||||
glDrawElementsInstanced(GL_LINES, 12, GL_UNSIGNED_INT, 0, num_instances);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Reset the rotation matrix to prevent continuous accumulation
|
||||
glm_mat4_identity(rotation_matrix);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Create the shader program
|
||||
GLuint create_shader_program ()
|
||||
{
|
||||
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex_shader, 1, &vertex_shader_src, NULL);
|
||||
glCompileShader(vertex_shader);
|
||||
|
||||
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment_shader, 1, &fragment_shader_src, NULL);
|
||||
glCompileShader(fragment_shader);
|
||||
|
||||
GLuint program = glCreateProgram();
|
||||
glAttachShader(program, vertex_shader);
|
||||
glAttachShader(program, fragment_shader);
|
||||
glLinkProgram(program);
|
||||
|
||||
glDeleteShader(vertex_shader);
|
||||
glDeleteShader(fragment_shader);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
// Setup OpenGL buffers (VBO, VAO, EBO for cubes and edges)
|
||||
void setup_buffers ()
|
||||
{
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
// Vertex buffer
|
||||
glGenBuffers(1, &vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||
|
||||
// Face Index buffer (EBO for cube faces)
|
||||
glGenBuffers(1, &ebo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
|
||||
|
||||
// Vertex attributes
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
// Edge Index buffer (EBO for cube edges)
|
||||
glGenBuffers(1, &edge_ebo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, edge_ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(edge_indices), edge_indices, GL_STATIC_DRAW);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void setup_arrow_buffers() {
|
||||
glGenVertexArrays(1, &arrow_vao);
|
||||
glBindVertexArray(arrow_vao);
|
||||
|
||||
// Vertex buffer for arrows
|
||||
glGenBuffers(1, &arrow_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, arrow_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(arrow_vertices), arrow_vertices, GL_STATIC_DRAW);
|
||||
|
||||
// Index buffer for arrows
|
||||
glGenBuffers(1, &arrow_ebo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrow_ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(arrow_indices), arrow_indices, GL_STATIC_DRAW);
|
||||
|
||||
// Vertex attributes
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
// Setup instance data for cubes (random positions)
|
||||
void setup_instance_data ()
|
||||
{
|
||||
g_message("[%s] setting up cube instance data...",
|
||||
__func__);
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
g_message("[%s] random seed initialized",
|
||||
__func__);
|
||||
|
||||
glGenBuffers(1, &instance_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, instance_vbo);
|
||||
|
||||
g_message("[%s] instance_vbo buffer bound",
|
||||
__func__);
|
||||
|
||||
for (unsigned int i = 0; i < num_instances; i++) {
|
||||
glm_mat4_identity(instance_matrices[i]);
|
||||
|
||||
// Randomize positions
|
||||
vec3 position = {
|
||||
(float)(rand() % N_SPACE_SIZE) - 10.0f, // Random x from -10 to 10
|
||||
(float)(rand() % N_SPACE_SIZE) - 10.0f, // Random y from -10 to 10
|
||||
(float)(rand() % N_SPACE_SIZE) - 10.0f // Random z from -10 to 10
|
||||
};
|
||||
|
||||
glm_translate(instance_matrices[i], position);
|
||||
}
|
||||
g_message("[%s] generated %d cube instances",
|
||||
__func__,
|
||||
num_instances);
|
||||
|
||||
// Pass the instance matrices to the instance VBO
|
||||
glBufferData(GL_ARRAY_BUFFER, num_instances * sizeof(mat4), instance_matrices, GL_STATIC_DRAW);
|
||||
|
||||
g_message("[%s] instance matrices passed to VBO",
|
||||
__func__);
|
||||
|
||||
// Setup vertex attribute for the model matrix (location = 2)
|
||||
// Setup vertex attribute for the model matrix (location = 2)
|
||||
glBindVertexArray(vao);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glVertexAttribPointer(2 + i, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (void*)(sizeof(vec4) * i));
|
||||
glEnableVertexAttribArray(2 + i);
|
||||
glVertexAttribDivisor(2 + i, 1); // Tell OpenGL this is per-instance data
|
||||
}
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
g_message("[%s] finalized model matrix vertex attribute ",
|
||||
__func__);
|
||||
}
|
||||
|
||||
void setup_arrow_instance_data() {
|
||||
// Define indices for the arrows (lines from center to cube faces)
|
||||
GLuint arrow_indices[] = {
|
||||
0, 1, // Arrow pointing to right face
|
||||
0, 2, // Arrow pointing upwards
|
||||
0, 3, // Arrow pointing to front face
|
||||
0, 4, // Arrow pointing to left face
|
||||
0, 5, // Arrow pointing downwards
|
||||
0, 6 // Arrow pointing to back face
|
||||
};
|
||||
|
||||
// Generate Vertex Array Object for arrows
|
||||
glGenVertexArrays(1, &arrow_vao);
|
||||
glBindVertexArray(arrow_vao);
|
||||
|
||||
// Generate Vertex Buffer Object for arrows
|
||||
GLuint arrow_vbo;
|
||||
glGenBuffers(1, &arrow_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, arrow_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(arrow_vertices), arrow_vertices, GL_STATIC_DRAW);
|
||||
|
||||
// Generate Element Buffer Object for arrows
|
||||
GLuint arrow_ebo;
|
||||
glGenBuffers(1, &arrow_ebo);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, arrow_ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(arrow_indices), arrow_indices, GL_STATIC_DRAW);
|
||||
|
||||
// Define arrow vertex attributes
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
// Arrow instance matrices (positions) -- same as cubes
|
||||
glGenBuffers(1, &arrow_instance_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, arrow_instance_vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, num_instances * sizeof(mat4), instance_matrices, GL_STATIC_DRAW);
|
||||
|
||||
// Define vertex attribute for arrow instance matrix
|
||||
for (int i = 0; i < 4; i++) {
|
||||
glVertexAttribPointer(2 + i, 4, GL_FLOAT, GL_FALSE, sizeof(mat4), (void*)(sizeof(vec4) * i));
|
||||
glEnableVertexAttribArray(2 + i);
|
||||
glVertexAttribDivisor(2 + i, 1); // Make this per-instance data
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
// Main Function
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
|
@ -595,4 +571,3 @@ int main (int argc, char *argv[])
|
|||
|
||||
return status;
|
||||
}
|
||||
|
Loading…
Reference in New Issue