Skip to content

Instantly share code, notes, and snippets.

@Lightnet
Created October 1, 2025 04:47
Show Gist options
  • Save Lightnet/e4b03d0bf7d982bc9d3b0663c02f316a to your computer and use it in GitHub Desktop.
Save Lightnet/e4b03d0bf7d982bc9d3b0663c02f316a to your computer and use it in GitHub Desktop.
Sample SDL 3.2 Flecs 4.1 cimgui 1.92 cube test render.

Flecs: 4.1 Glad: 2.0.8 opengl: 330 sdl: 3.2 just sample test. cimgui: 1.92

This is just cube render set up test.

// module_font.c
#include "module_font.h"
#include <stdio.h>
#include <stdlib.h>
#define STB_TRUETYPE_IMPLEMENTATION
#include "stb_truetype.h"
// Define FontData locally
struct FontData {
GLuint texture; // Font texture ID
stbtt_bakedchar* cdata; // Character data (ASCII 32..127)
int bitmap_w, bitmap_h; // Bitmap dimensions
};
// Static FontData for alternative functions
static struct FontData* global_font_data = NULL;
// Initialize font: Load TTF and bake bitmap
int init_font(const char* font_path, float font_size, float scale, FontData** font_data) {
*font_data = (struct FontData*)malloc(sizeof(struct FontData));
if (!*font_data) {
printf("Error: Failed to allocate FontData\n");
return 0;
}
unsigned char* ttf_buffer = (unsigned char*)malloc(1 << 20);
if (!ttf_buffer) {
printf("Error: Failed to allocate TTF buffer\n");
free(*font_data);
*font_data = NULL;
return 0;
}
FILE* ff = fopen(font_path, "rb");
if (!ff) {
printf("Error: Failed to open font file '%s'\n", font_path);
free(ttf_buffer);
free(*font_data);
*font_data = NULL;
return 0;
}
fread(ttf_buffer, 1, 1 << 20, ff);
fclose(ff);
(*font_data)->bitmap_w = 512;
(*font_data)->bitmap_h = 512;
unsigned char* bitmap = (unsigned char*)malloc((*font_data)->bitmap_w * (*font_data)->bitmap_h);
if (!bitmap) {
printf("Error: Failed to allocate bitmap\n");
free(ttf_buffer);
free(*font_data);
*font_data = NULL;
return 0;
}
(*font_data)->cdata = (stbtt_bakedchar*)malloc(96 * sizeof(stbtt_bakedchar));
if (!(*font_data)->cdata) {
printf("Error: Failed to allocate cdata\n");
free(bitmap);
free(ttf_buffer);
free(*font_data);
*font_data = NULL;
return 0;
}
stbtt_BakeFontBitmap(ttf_buffer, 0, font_size * scale, bitmap, (*font_data)->bitmap_w, (*font_data)->bitmap_h, 32, 96, (*font_data)->cdata);
free(ttf_buffer);
// Create OpenGL texture
glGenTextures(1, &(*font_data)->texture);
glBindTexture(GL_TEXTURE_2D, (*font_data)->texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, (*font_data)->bitmap_w, (*font_data)->bitmap_h, 0, GL_RED, GL_UNSIGNED_BYTE, bitmap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
free(bitmap);
return 1;
}
// Render text
void render_text(FontData* font_data, GLuint program, GLuint vao, GLuint vbo, const char* text, float x, float y, int ww, int hh, float r, float g, float b, float a) {
if (!font_data) return;
float vertices[1024 * 4]; // Enough for simple text
int vert_count = 0;
for (const char* p = text; *p; p++) {
if (*p >= 32 && *p < 128) {
stbtt_aligned_quad q;
stbtt_GetBakedQuad(font_data->cdata, font_data->bitmap_w, font_data->bitmap_h, *p - 32, &x, &y, &q, 1);
float nx0 = 2.0f * q.x0 / ww - 1.0f;
float ny0 = 1.0f - 2.0f * q.y0 / hh;
float nx1 = 2.0f * q.x1 / ww - 1.0f;
float ny1 = 1.0f - 2.0f * q.y1 / hh;
// Triangle 1
vertices[vert_count++] = nx0; vertices[vert_count++] = ny0; vertices[vert_count++] = q.s0; vertices[vert_count++] = q.t0;
vertices[vert_count++] = nx1; vertices[vert_count++] = ny0; vertices[vert_count++] = q.s1; vertices[vert_count++] = q.t0;
vertices[vert_count++] = nx1; vertices[vert_count++] = ny1; vertices[vert_count++] = q.s1; vertices[vert_count++] = q.t1;
// Triangle 2
vertices[vert_count++] = nx0; vertices[vert_count++] = ny0; vertices[vert_count++] = q.s0; vertices[vert_count++] = q.t0;
vertices[vert_count++] = nx1; vertices[vert_count++] = ny1; vertices[vert_count++] = q.s1; vertices[vert_count++] = q.t1;
vertices[vert_count++] = nx0; vertices[vert_count++] = ny1; vertices[vert_count++] = q.s0; vertices[vert_count++] = q.t1;
}
}
glUseProgram(program);
glUniform1i(glGetUniformLocation(program, "textTexture"), 0);
glUniform4f(glGetUniformLocation(program, "textColor"), r, g, b, a);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, font_data->texture);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vert_count * sizeof(float), vertices, GL_DYNAMIC_DRAW);
glDrawArrays(GL_TRIANGLES, 0, vert_count / 4);
glBindVertexArray(0);
}
// Clean up font resources
void cleanup_font(FontData* font_data) {
if (!font_data) return;
glDeleteTextures(1, &font_data->texture);
free(font_data->cdata);
free(font_data);
}
// Alternative functions using a static FontData
int init_font_alt(const char* font_path, float font_size, float scale) {
if (global_font_data) {
cleanup_font(global_font_data);
}
return init_font(font_path, font_size, scale, &global_font_data);
}
void render_text_alt(GLuint program, GLuint vao, GLuint vbo, const char* text, float x, float y, int ww, int hh, float r, float g, float b, float a) {
if (global_font_data) {
render_text(global_font_data, program, vao, vbo, text, x, y, ww, hh, r, g, b, a);
}
}
void cleanup_font_alt(void) {
if (global_font_data) {
cleanup_font(global_font_data);
global_font_data = NULL;
}
}
// Initialize shaders and VAO/VBO
int init_font_shaders_and_buffers(GLuint* program, GLuint* vao, GLuint* vbo) {
const char* vs_src =
"#version 330 core\n"
"layout(location = 0) in vec2 position;\n"
"layout(location = 1) in vec2 texCoord;\n"
"out vec2 TexCoord;\n"
"void main() {\n"
" gl_Position = vec4(position, 0.0, 1.0);\n"
" TexCoord = texCoord;\n"
"}\n";
const char* fs_src =
"#version 330 core\n"
"in vec2 TexCoord;\n"
"out vec4 FragColor;\n"
"uniform sampler2D textTexture;\n"
"uniform vec4 textColor;\n"
"void main() {\n"
" float alpha = texture(textTexture, TexCoord).r;\n"
" FragColor = vec4(textColor.rgb, alpha * textColor.a);\n"
"}\n";
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vs_src, NULL);
glCompileShader(vs);
GLint success;
glGetShaderiv(vs, GL_COMPILE_STATUS, &success);
if (!success) {
char info_log[512];
glGetShaderInfoLog(vs, 512, NULL, info_log);
printf("Vertex shader compilation failed: %s\n", info_log);
return 0;
}
GLuint fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fs_src, NULL);
glCompileShader(fs);
glGetShaderiv(fs, GL_COMPILE_STATUS, &success);
if (!success) {
char info_log[512];
glGetShaderInfoLog(fs, 512, NULL, info_log);
printf("Fragment shader compilation failed: %s\n", info_log);
glDeleteShader(vs);
return 0;
}
*program = glCreateProgram();
glAttachShader(*program, vs);
glAttachShader(*program, fs);
glLinkProgram(*program);
glGetProgramiv(*program, GL_LINK_STATUS, &success);
if (!success) {
char info_log[512];
glGetProgramInfoLog(*program, 512, NULL, info_log);
printf("Program linking failed: %s\n", info_log);
glDeleteShader(vs);
glDeleteShader(fs);
return 0;
}
glDeleteShader(vs);
glDeleteShader(fs);
glGenVertexArrays(1, vao);
glGenBuffers(1, vbo);
glBindVertexArray(*vao);
glBindBuffer(GL_ARRAY_BUFFER, *vbo);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
glBindVertexArray(0);
return 1;
}
// module_font.h
#pragma once
// #ifndef MODULE_FONT_H
// #define MODULE_FONT_H
#include <glad/gl.h>
// Opaque pointer to FontData
typedef struct FontData FontData;
int init_font_shaders_and_buffers(GLuint* program, GLuint* vao, GLuint* vbo);
// Functions using FontData
int init_font(const char* font_path, float font_size, float scale, FontData** font_data);
void render_text(FontData* font_data, GLuint program, GLuint vao, GLuint vbo, const char* text, float x, float y, int ww, int hh, float r, float g, float b, float a);
void cleanup_font(FontData* font_data);
// Alternative functions (no FontData, for internal management)
int init_font_alt(const char* font_path, float font_size, float scale);
void render_text_alt(GLuint program, GLuint vao, GLuint vbo, const char* text, float x, float y, int ww, int hh, float r, float g, float b, float a);
void cleanup_font_alt(void);
// #endif // MODULE_FONT_H
/*
// refs
typedef struct {
GLuint texture;
stbtt_bakedchar* cdata;
int bitmap_w, bitmap_h;
} FontData;
render_text(&font_data, text_program, text_vao, text_vbo, text, 25.0f, 150.0f, ww, hh, 1.0f, 1.0f, 1.0f, 1.0f);
*/
//
#include <SDL3/SDL.h>
#include <glad/gl.h>
#include <stdio.h>
#include <stdlib.h>
#include <cimgui.h>
#include <cimgui_impl.h>
#include "module_font.h"
#include <cglm/cglm.h> // Include CGLM
#include "flecs.h"
#define igGetIO igGetIO_Nil
typedef struct {
float x;
float y;
} Position;
typedef struct {
float x;
float y;
} Velocity;
typedef struct {
vec3 position; // Vector3 for position (x, y, z)
vec3 rotation; // Euler angles in degrees (x, y, z)
vec3 scale; // Scale (x, y, z)
mat4 local; // Local transformation matrix
mat4 world; // World transformation matrix
bool isDirty; // Flag to indicate if transform needs recalculation
} Transform3D;
ECS_COMPONENT_DECLARE(Transform3D);
typedef struct {
GLuint vao, vbo, ebo; // OpenGL buffer objects
GLuint shaderProgram; // Shader program for the cube
int indexCount; // Number of indices for rendering
} CubeContext;
// Cube vertices: position (x, y, z)
static const float cubeVertices[] = {
// Front face
-0.5f, -0.5f, 0.5f, // 0
0.5f, -0.5f, 0.5f, // 1
0.5f, 0.5f, 0.5f, // 2
-0.5f, 0.5f, 0.5f, // 3
// Back face
-0.5f, -0.5f, -0.5f, // 4
0.5f, -0.5f, -0.5f, // 5
0.5f, 0.5f, -0.5f, // 6
-0.5f, 0.5f, -0.5f // 7
};
// Indices for the cube (6 faces, 2 triangles per face, 3 vertices per triangle)
static const unsigned int cubeIndices[] = {
// Front
0, 1, 2, 2, 3, 0,
// Right
1, 5, 6, 6, 2, 1,
// Back
5, 4, 7, 7, 6, 5,
// Left
4, 0, 3, 3, 7, 4,
// Top
3, 2, 6, 6, 7, 3,
// Bottom
4, 5, 1, 1, 0, 4
};
bool init_cube_mesh(CubeContext* cube) {
// Vertex Shader
const char* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main() {\n"
" gl_Position = projection * view * model * vec4(aPos, 1.0);\n"
"}\n";
// Fragment Shader (simple color)
const char* fragmentShaderSource = "#version 330 core\n"
"out vec4 FragColor;\n"
"void main() {\n"
" FragColor = vec4(1.0, 0.5, 0.2, 1.0);\n" // Orange color
"}\n";
// Compile shaders
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
glCompileShader(vertexShader);
GLint success;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
printf("Vertex Shader Compilation Failed: %s\n", infoLog);
return false;
}
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
glCompileShader(fragmentShader);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
printf("Fragment Shader Compilation Failed: %s\n", infoLog);
return false;
}
cube->shaderProgram = glCreateProgram();
glAttachShader(cube->shaderProgram, vertexShader);
glAttachShader(cube->shaderProgram, fragmentShader);
glLinkProgram(cube->shaderProgram);
glGetProgramiv(cube->shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
char infoLog[512];
glGetProgramInfoLog(cube->shaderProgram, 512, NULL, infoLog);
printf("Shader Program Linking Failed: %s\n", infoLog);
return false;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
// Setup VAO, VBO, EBO
glGenVertexArrays(1, &cube->vao);
glGenBuffers(1, &cube->vbo);
glGenBuffers(1, &cube->ebo);
glBindVertexArray(cube->vao);
glBindBuffer(GL_ARRAY_BUFFER, cube->vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeVertices), cubeVertices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cube->ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), cubeIndices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
glBindVertexArray(0);
cube->indexCount = sizeof(cubeIndices) / sizeof(cubeIndices[0]);
return true;
}
void update_transform_system(ecs_iter_t *it) {
Transform3D *transforms = ecs_field(it, Transform3D, 0);
for (int i = 0; i < it->count; i++) {
if (!transforms[i].isDirty) continue;
mat4 local;
glm_mat4_identity(local);
glm_scale(local, transforms[i].scale);
glm_rotate_x(local, glm_rad(transforms[i].rotation[0]), local);
glm_rotate_y(local, glm_rad(transforms[i].rotation[1]), local);
glm_rotate_z(local, glm_rad(transforms[i].rotation[2]), local);
glm_translate(local, transforms[i].position);
glm_mat4_copy(local, transforms[i].local);
glm_mat4_copy(local, transforms[i].world); // No parent transform
transforms[i].isDirty = false;
printf("Updated transform %d: Pos=(%.2f, %.2f, %.2f)\n",
i, transforms[i].position[0], transforms[i].position[1], transforms[i].position[2]);
}
}
// void update_transform_system(ecs_iter_t *it) {
// Transform3D *transforms = ecs_field(it, Transform3D, 0);
// for (int i = 0; i < it->count; i++) {
// if (!transforms[i].isDirty) continue;
// // Calculate local matrix
// mat4 local;
// glm_mat4_identity(local);
// // Apply scale
// glm_scale(local, transforms[i].scale);
// // Apply rotation (Euler angles in degrees)
// glm_rotate_x(local, glm_rad(transforms[i].rotation[0]), local);
// glm_rotate_y(local, glm_rad(transforms[i].rotation[1]), local);
// glm_rotate_z(local, glm_rad(transforms[i].rotation[2]), local);
// // Apply translation
// glm_translate(local, transforms[i].position);
// glm_mat4_copy(local, transforms[i].local);
// // Check for parent transform
// ecs_entity_t parent = ecs_get_parent(it->world, it->entities[i]);
// if (parent && ecs_has(it->world, parent, Transform3D)) {
// Transform3D *parent_transform = ecs_get_mut(it->world, parent, Transform3D);
// mat4 world;
// glm_mat4_mul(parent_transform->world, local, world);
// glm_mat4_copy(world, transforms[i].world);
// } else {
// glm_mat4_copy(local, transforms[i].world);
// }
// transforms[i].isDirty = false;
// }
// }
void render_3d_cube_system(ecs_iter_t *it) {
Transform3D *transforms = ecs_field(it, Transform3D, 0);
CubeContext *cube = (CubeContext *)ecs_get_ctx(it->world);
if (!cube) {
printf("CubeContext is NULL in render_3d_cube_system!\n");
return;
}
printf("Rendering %d cubes\n", it->count);
if (it->count == 0) {
printf("No entities with Transform3D found!\n");
return;
}
glUseProgram(cube->shaderProgram);
// Ensure depth testing is enabled
glEnable(GL_DEPTH_TEST);
// Setup view and projection matrices
mat4 view, projection;
glm_mat4_identity(view);
glm_lookat((vec3){0.0f, 0.0f, 5.0f}, (vec3){0.0f, 0.0f, 0.0f}, (vec3){0.0f, 1.0f, 0.0f}, view);
int ww, hh;
SDL_GetWindowSize(SDL_GL_GetCurrentWindow(), &ww, &hh);
glm_perspective(glm_rad(45.0f), (float)ww / hh, 0.1f, 100.0f, projection);
GLint modelLoc = glGetUniformLocation(cube->shaderProgram, "model");
GLint viewLoc = glGetUniformLocation(cube->shaderProgram, "view");
GLint projLoc = glGetUniformLocation(cube->shaderProgram, "projection");
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, (float*)view);
glUniformMatrix4fv(projLoc, 1, GL_FALSE, (float*)projection);
glBindVertexArray(cube->vao);
for (int i = 0; i < it->count; i++) {
printf("Rendering cube %d: Pos=(%.2f, %.2f, %.2f), Rot=(%.2f, %.2f, %.2f), Scale=(%.2f, %.2f, %.2f)\n",
i, transforms[i].position[0], transforms[i].position[1], transforms[i].position[2],
transforms[i].rotation[0], transforms[i].rotation[1], transforms[i].rotation[2],
transforms[i].scale[0], transforms[i].scale[1], transforms[i].scale[2]);
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, (float*)transforms[i].world);
glDrawElements(GL_TRIANGLES, cube->indexCount, GL_UNSIGNED_INT, 0);
}
glBindVertexArray(0);
// Check for OpenGL errors
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR) {
printf("OpenGL Error in render_3d_cube_system: %u\n", err);
}
}
// nope error on attach child
// void start_up_system(ecs_iter_t *it) {
// printf("start up\n");
// // Create parent cube
// ecs_entity_t parent = ecs_entity(it->world, { .name = "ParentCube" });
// ecs_set(it->world, parent, Transform3D, {
// .position = {0.0f, 0.0f, 0.0f},
// .rotation = {0.0f, 0.0f, 0.0f},
// .scale = {1.0f, 1.0f, 1.0f},
// .isDirty = true
// });
// // Create child cube
// ecs_entity_t child = ecs_entity(it->world, { .name = "ChildCube" });
// ecs_set(it->world, child, Transform3D, {
// .position = {2.0f, 0.0f, 0.0f}, // Offset from parent
// .rotation = {0.0f, 45.0f, 0.0f},
// .scale = {0.5f, 0.5f, 0.5f},
// .isDirty = true
// });
// ecs_add_pair(it->world, child, EcsChildOf, parent);
// // Initialize cube mesh
// CubeContext* cube = malloc(sizeof(CubeContext));
// if (!init_cube_mesh(cube)) {
// printf("Failed to initialize cube mesh\n");
// return;
// }
// ecs_set_ctx(it->world, cube, NULL);
// }
int main() {
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) {
fprintf(stderr, "Failed to init video! %s\n", SDL_GetError());
return 1;
}
float main_scale = SDL_GetDisplayContentScale(SDL_GetPrimaryDisplay());
SDL_WindowFlags window_flags = SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIDDEN | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_OPENGL;
SDL_Window* window = SDL_CreateWindow("SDL3 OpenGL Font Tranformer 3d", (int)(1280 * main_scale), (int)(720 * main_scale), window_flags);
if (!window) {
printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError());
SDL_Quit();
return -1;
}
SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window);
// Create OpenGL context
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GLContext gl_context = SDL_GL_CreateContext(window);
if (!gl_context) {
printf("Error: SDL_GL_CreateContext(): %s\n", SDL_GetError());
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
SDL_GL_MakeCurrent(window, gl_context);
int version = gladLoadGL((GLADloadfunc)SDL_GL_GetProcAddress);
if (version == 0) {
printf("Failed to initialize GLAD\n");
SDL_GL_DestroyContext(gl_context);
SDL_DestroyWindow(window);
SDL_Quit();
return 1;
}
printf("OpenGL loaded: version %s\n", glGetString(GL_VERSION));
FontData *font_data = NULL;
if (!init_font("resources/Kenney Mini.ttf", 32.0f, main_scale, &font_data)) {
SDL_GL_DestroyContext(gl_context);
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
// Initialize shaders and buffers
GLuint program, vao, vbo;
if (!init_font_shaders_and_buffers(&program, &vao, &vbo)) {
// cleanup_font(&font_data);
cleanup_font(font_data);
SDL_GL_DestroyContext(gl_context);
SDL_DestroyWindow(window);
SDL_Quit();
return -1;
}
// Setup Dear ImGui context
igCreateContext(NULL);
ImGuiIO* io = igGetIO();
io->ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
io->ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
// Setup Dear ImGui style
igStyleColorsDark(NULL);
ImGuiStyle* style = igGetStyle();
ImGuiStyle_ScaleAllSizes(style, main_scale);
// Setup Platform/Renderer backends
ImGui_ImplSDL3_InitForOpenGL(window, gl_context);
ImGui_ImplOpenGL3_Init("#version 330");
// Our state
bool show_demo_window = true;
bool show_another_window = false;
float clear_colorE4[4] = {0.45f, 0.55f, 0.60f, 1.00f};
ImVec4 clearColorE3;
clearColorE3.x = 0.45f;
clearColorE3.y = 0.55f;
clearColorE3.z = 0.60f;
clearColorE3.w = 1.00f;
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
float clear_color[4] = {0.45f, 0.55f, 0.60f, 1.00f};
bool done = false;
const char* text = "Hello World! Glad 2.0.8";
ecs_world_t *world = ecs_init();
CubeContext* cube;
ECS_COMPONENT(world, Position);
ECS_COMPONENT(world, Velocity);
// ECS_COMPONENT(world, CubeContext);
ECS_COMPONENT(world, Transform3D);
// EcsOnStart
// EcsPreUpdate
// EcsOnUpdate
// EcsPostUpdate
// start up system
// ECS_SYSTEM(world, start_up_system, EcsOnStart);
ECS_SYSTEM(world, update_transform_system, EcsPreUpdate, Transform3D);
//render 3d cube
ECS_SYSTEM(world, render_3d_cube_system, EcsOnUpdate, Transform3D);
// Create parent cube
ecs_entity_t parent = ecs_entity(world, { .name = "ParentCube" });
ecs_set(world, parent, Transform3D, {
.position = {0.0f, 0.0f, 0.0f},
.rotation = {0.0f, 0.0f, 0.0f},
.scale = {1.0f, 1.0f, 1.0f},
.isDirty = true
});
// Create child cube
ecs_entity_t child = ecs_entity(world, { .name = "ChildCube" });
ecs_set(world, child, Transform3D, {
// .position = {2.0f, 0.0f, 0.0f}, // Offset from parent
.position = {0.0f, 0.0f, 0.0f}, // Offset from parent
// .rotation = {0.0f, 0.0f, 0.0f},
.rotation = {0.0f, 45.0f, 0.0f},
.scale = {1.0f, 1.0f, 1.0f},
.isDirty = true
});
ecs_add_pair(world, child, EcsChildOf, parent);
// Initialize cube mesh
cube = malloc(sizeof(CubeContext));
if (!init_cube_mesh(cube)) {
printf("Failed to initialize cube mesh\n");
// return;
}
ecs_set_ctx(world, cube, NULL);
// Do the ECS stuff
ecs_entity_t e = ecs_entity(world, { .name = "Bob" });
printf("Entity name: %s\n", ecs_get_name(world, e));
// glEnable(GL_DEPTH_TEST);
while (!done) {
SDL_Event event;
while (SDL_PollEvent(&event)) {
ImGui_ImplSDL3_ProcessEvent(&event);
if (event.type == SDL_EVENT_QUIT)
done = true;
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window))
done = true;
}
if (SDL_GetWindowFlags(window) & SDL_WINDOW_MINIMIZED) {
SDL_Delay(10);
continue;
}
// Start the Dear ImGui frame
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplSDL3_NewFrame();
igNewFrame();
// Simple window
{
static float f = 0.0f;
static int counter = 0;
// igBegin("Hello, world!", NULL, 0);
// igText("This is some useful text.");
// igCheckbox("Demo Window", &show_demo_window);
// igCheckbox("Another Window", &show_another_window);
// igSliderFloat("float", &f, 0.0f, 1.0f, "%.3f", 0);
// igText("Choose a color:");
// if(igColorEdit4("clear color E4", (float*)&clear_colorE4, 0)){
// // Log the new color values whenever they change
// printf("Color changed to: R=%.2f, G=%.2f, B=%.2f, A=%.2f\n",
// clear_colorE4[0], clear_colorE4[1], clear_colorE4[2], clear_colorE4[3]);
// }
// igColorEdit3("clear color E3", (float *)&clearColorE3, 0);
// ImVec2 buttonSize = {0, 0};
// if (igButton("Button", buttonSize))
// counter++;
// igSameLine(0.0f, -1.0f);
// igText("counter = %d", counter);
// igText("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / io->Framerate, io->Framerate);
// igEnd();
}
{
igBegin("transform3d", NULL, 0);
ImVec2 buttonSize = {0, 0};
if (igButton("query", buttonSize)){
}
igEnd();
}
// Rendering
igRender();
int ww, hh;
SDL_GetWindowSize(window, &ww, &hh);
glViewport(0, 0, ww, hh);
glViewport(0, 0, (int)io->DisplaySize.x, (int)io->DisplaySize.y); //cimgui
glClearColor(clear_colorE4[0], clear_colorE4[1], clear_colorE4[2], clear_colorE4[3]);
// glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
// glClear(GL_COLOR_BUFFER_BIT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Enable depth testing for 3D rendering
glEnable(GL_DEPTH_TEST);
// Test cube rendering
// {
// printf("Test cube rendering\n");
// glUseProgram(cube->shaderProgram);
// // Setup view and projection matrices (same as render_3d_cube_system)
// mat4 view, projection;
// glm_mat4_identity(view);
// glm_lookat((vec3){0.0f, 0.0f, 5.0f}, (vec3){0.0f, 0.0f, 0.0f}, (vec3){0.0f, 1.0f, 0.0f}, view);
// glm_perspective(glm_rad(45.0f), (float)ww / hh, 0.1f, 100.0f, projection);
// // Simple model matrix (e.g., translate to (0, 0, 0) with no rotation or scale)
// mat4 model;
// glm_mat4_identity(model);
// // Optional: Translate to make sure it’s visible
// glm_translate(model, (vec3){0.0f, 0.0f, 0.0f});
// // Set uniforms
// GLint modelLoc = glGetUniformLocation(cube->shaderProgram, "model");
// GLint viewLoc = glGetUniformLocation(cube->shaderProgram, "view");
// GLint projLoc = glGetUniformLocation(cube->shaderProgram, "projection");
// glUniformMatrix4fv(modelLoc, 1, GL_FALSE, (float*)model);
// glUniformMatrix4fv(viewLoc, 1, GL_FALSE, (float*)view);
// glUniformMatrix4fv(projLoc, 1, GL_FALSE, (float*)projection);
// // Draw the cube
// glBindVertexArray(cube->vao);
// glDrawElements(GL_TRIANGLES, cube->indexCount, GL_UNSIGNED_INT, 0);
// glBindVertexArray(0);
// // Check for OpenGL errors
// GLenum err;
// while ((err = glGetError()) != GL_NO_ERROR) {
// printf("OpenGL Error during test render: %u\n", err);
// }
// }
ecs_progress(world, 0); // run systems in default pipeline
// Render 2D text
// render_text(&font_data, program, vao, vbo, text, 25.0f, 150.0f, ww, hh, 1.0f, 1.0f, 1.0f, 1.0f);// test
render_text(font_data, program, vao, vbo, "Hello, World!", 100.0f, 100.0f, ww, hh, 1.0f, 1.0f, 1.0f, 1.0f);
ImGui_ImplOpenGL3_RenderDrawData(igGetDrawData());
SDL_GL_SwapWindow(window);
}
// Cleanup
// CubeContext* cube = ecs_get_ctx(world);
// cube = ecs_get_ctx(world);
if (cube) {
glDeleteVertexArrays(1, &cube->vao);
glDeleteBuffers(1, &cube->vbo);
glDeleteBuffers(1, &cube->ebo);
glDeleteProgram(cube->shaderProgram);
free(cube);
}
ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplSDL3_Shutdown();
igDestroyContext(NULL);
cleanup_font(font_data); // conflict due cimgui modified font match data type.
glDeleteProgram(program);
glDeleteBuffers(1, &vbo);
glDeleteVertexArrays(1, &vao);
ecs_fini(world);
SDL_GL_DestroyContext(gl_context);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment