/* a rendering.c mixin */ #ifndef CIRCLES_H #define CIRCLES_H #include "../util.h" #include "../private/rendering.h" #include "../context.h" #include #include #include void push_circle(t_fvec2 position, float radius, t_color color) { struct circle_primitive circle = { .radius = radius, .color = color, .position = position, }; struct primitive_2d primitive = { .type = PRIMITIVE_2D_CIRCLE, .circle = circle, }; arrput(ctx.render_queue_2d, primitive); } /* TODO: caching and reuse scheme */ /* vertices_out and indices_out MUST BE FREED */ static void create_circle_geometry(t_fvec2 position, t_color color, float radius, size_t num_vertices, SDL_Vertex **vertices_out, int **indices_out) { SDL_Vertex *vertices = cmalloc(sizeof *vertices * (num_vertices + 1)); int *indices = cmalloc(sizeof *indices * (num_vertices * 3)); /* the angle (in radians) to rotate by on each iteration */ float seg_rotation_angle = (360.0f / (float)num_vertices) * ((float)M_PI / 180); vertices[0].position.x = (float)position.x; vertices[0].position.y = (float)position.y; vertices[0].color.r = color.r; vertices[0].color.g = color.g; vertices[0].color.b = color.b; vertices[0].color.a = color.a; vertices[0].tex_coord = (SDL_FPoint){ 0, 0 }; /* this point will rotate around the center */ float start_x = 0.0f - radius; float start_y = 0.0f; for (size_t i = 1; i < num_vertices + 1; ++i) { float final_seg_rotation_angle = (float)i * seg_rotation_angle; vertices[i].position.x = cosf(final_seg_rotation_angle) * start_x - sinf(final_seg_rotation_angle) * start_y; vertices[i].position.y = cosf(final_seg_rotation_angle) * start_y + sinf(final_seg_rotation_angle) * start_x; vertices[i].position.x += position.x; vertices[i].position.y += position.y; vertices[i].color.r = color.r; vertices[i].color.g = color.g; vertices[i].color.b = color.b; vertices[i].color.a = color.a; vertices[i].tex_coord = (SDL_FPoint){ 0, 0 }; size_t triangle_offset = 3 * (i - 1); /* center point index */ indices[triangle_offset] = 0; /* generated point index */ indices[triangle_offset + 1] = (int)i; size_t index = (i + 1) % num_vertices; if (index == 0) index = num_vertices; indices[triangle_offset + 2] = (int)index; } *vertices_out = vertices; *indices_out = indices; } static void render_circle(const struct circle_primitive *circle) { SDL_Vertex *vertices = NULL; int *indices = NULL; int num_vertices = (int)circle->radius; create_circle_geometry(circle->position, circle->color, circle->radius, num_vertices, &vertices, &indices); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(2, GL_FLOAT, sizeof (SDL_Vertex), &vertices->position); glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_UNSIGNED_BYTE, sizeof (SDL_Vertex), &vertices->color); glDrawElements(GL_TRIANGLES, num_vertices * 3, GL_UNSIGNED_INT, indices); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); free(vertices); free(indices); } #endif