Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix images not appearing #54

Merged
merged 5 commits into from
Aug 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 5 additions & 17 deletions include/MLX42/MLX42.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,15 @@ typedef struct xpm
*
* @param x The x location.
* @param y The y location.
* @param z The z depth, controls if the image is on the fore or background.
* @param custom_depth The custom z depth, controls if the image is on the fore or background.
* @param enabled If true, the instance is drawn else its not.
*/
typedef struct mlx_instance
{
int32_t x;
int32_t y;
int32_t z;
bool enabled;
int32_t x;
int32_t y;
int32_t custom_depth;
bool enabled;
} mlx_instance_t;

/**
Expand Down Expand Up @@ -678,18 +678,6 @@ void mlx_delete_image(mlx_t* mlx, mlx_image_t* image);
*/
bool mlx_resize_image(mlx_image_t* img, uint32_t nwidth, uint32_t nheight);

/**
* Sets the depth / Z axis value of an instance.
*
* NOTE: Keep in mind that images that are on the same Z layer, cut each other off.
* so if you don't see your image anymore make sure its not conflicting by being on
* the same layer as another image.
*
* @param[in] instance The instane on which to change the depth.
* @param[in] zdepth The new depth value.
*/
void mlx_set_instance_depth(mlx_instance_t* instance, int32_t zdepth);

//= String Functions =//

/**
Expand Down
35 changes: 31 additions & 4 deletions include/MLX42/MLX42_Int.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ typedef struct mlx_list
struct mlx_list* prev;
} mlx_list_t;

typedef struct mlx_vec
{
void* data;
int32_t count;

size_t capacity;
size_t elementSize;
int32_t position;
} mlx_vec_t;

//= Hook structs =//
/**
* There are 2 types of hooks, special and generics.
Expand Down Expand Up @@ -185,7 +195,8 @@ typedef struct mlx_ctx

mlx_list_t* hooks;
mlx_list_t* images;
mlx_list_t* render_queue;
mlx_vec_t render_queue;
int32_t instance_count;

mlx_scroll_t scroll_hook;
mlx_mouse_t mouse_hook;
Expand All @@ -205,6 +216,7 @@ typedef struct draw_queue
{
mlx_image_t* image;
int32_t instanceid;
int32_t caluclatedDepth;
} draw_queue_t;

// Image context.
Expand All @@ -215,6 +227,7 @@ typedef struct mlx_image_ctx
} mlx_image_ctx_t;

//= Functions =//

/**
* All sorts of internal functions shared in the library that
* should not be accessible to the user! No touch!
Expand All @@ -229,7 +242,6 @@ void mlx_lstclear(mlx_list_t** lst, void (*del)(void*));
void mlx_lstadd_back(mlx_list_t** lst, mlx_list_t* new);
void mlx_lstadd_front(mlx_list_t** lst, mlx_list_t* new);
mlx_list_t* mlx_lstremove(mlx_list_t** lst, void* value, bool (*comp)(void*, void*));
void mlx_sort_renderqueue(mlx_list_t** lst);

//= Misc functions =//

Expand All @@ -245,13 +257,28 @@ bool mlx_freen(int32_t count, ...);
//= OpenGL Functions =//

void mlx_update_matrix(const mlx_t* mlx, int32_t width, int32_t height);
void mlx_draw_instance(mlx_ctx_t* mlx, mlx_image_t* img, mlx_instance_t* instance);
void mlx_draw_instance(mlx_ctx_t* mlx, mlx_image_t* img, mlx_instance_t* instance, int32_t instanceDepth);
void mlx_flush_batch(mlx_ctx_t* mlx);

// Utils Functions =//
//= Utils Functions =//

bool mlx_getline(char** out, size_t* out_size, FILE* file);
uint32_t mlx_rgba_to_mono(uint32_t color);
int32_t mlx_atoi_base(const char* str, int32_t base);
uint64_t mlx_fnv_hash(char* str, size_t len);

void mlx_render_queue_sort(mlx_vec_t *render_queue);

//= Image Helper Functions =//
int32_t mlx_image_calculate_max_depth(mlx_image_t *image);

//= Vector Functions =//

bool mlx_vector_init(mlx_vec_t* v, size_t elementSize);
bool mlx_vector_push_back(mlx_vec_t* v, void* item);
void mlx_vector_set(mlx_vec_t* v, int32_t index, void* item);
void* mlx_vector_get(mlx_vec_t* v, int32_t index);
bool mlx_vector_delete(mlx_vec_t* v, int32_t index);
void mlx_vector_free(mlx_vec_t* v);
void mlx_vector_swap(mlx_vec_t* v, int32_t srcIndex, int32_t dstIndex);
#endif
2 changes: 1 addition & 1 deletion src/font/mlx_font.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ int32_t mlx_get_texoffset(char c)
{
const bool _isprint = isprint(c);

// NOTE: Cheesy branchless operation :D
// NOTE(W2): Cheesy branchless operation :D
// +2 To skip line separator in texture
return (-1 * !_isprint + ((FONT_WIDTH + 2) * (c - 32)) * _isprint);
}
Expand Down
2 changes: 1 addition & 1 deletion src/mlx_exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void mlx_terminate(mlx_t* mlx)

glfwTerminate();
mlx_lstclear((mlx_list_t**)(&mlxctx->hooks), &free);
mlx_lstclear((mlx_list_t**)(&mlxctx->render_queue), &free);
mlx_lstclear((mlx_list_t**)(&mlxctx->images), &mlx_free_image);
mlx_vector_free(&mlxctx->render_queue);
mlx_freen(2, mlxctx, mlx);
}
133 changes: 68 additions & 65 deletions src/mlx_images.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,22 @@ static int8_t mlx_bind_texture(mlx_ctx_t* mlx, mlx_image_t* img)
* Internal function to draw a single instance of an image
* to the screen.
*/
void mlx_draw_instance(mlx_ctx_t* mlx, mlx_image_t* img, mlx_instance_t* instance)
void mlx_draw_instance(mlx_ctx_t* mlx, mlx_image_t* img, mlx_instance_t* instance, int32_t instanceDepth)
{
float w = (float) img->width;
float h = (float) img->height;
float x = (float) instance->x;
float y = (float) instance->y;
float z = (float) instance->z;
float w = (float)img->width;
float h = (float)img->height;
float x = (float)instance->x;
float y = (float)instance->y;
float z = (float)instanceDepth;
int8_t tex = mlx_bind_texture(mlx, img);

vertex_t vertices[6] = {
(vertex_t){x, y, z, 0.f, 0.f, tex},
(vertex_t){x + w, y + h, z, 1.f, 1.f, tex},
(vertex_t){x + w, y, z, 1.f, 0.f, tex},
(vertex_t){x, y, z, 0.f, 0.f, tex},
(vertex_t){x, y + h, z, 0.f, 1.f, tex},
(vertex_t){x + w, y + h, z, 1.f, 1.f, tex},
(vertex_t){x, y, z, 0.f, 0.f, tex},
(vertex_t){x + w, y + h, z, 1.f, 1.f, tex},
(vertex_t){x + w, y, z, 1.f, 0.f, tex},
(vertex_t){x, y, z, 0.f, 0.f, tex},
(vertex_t){x, y + h, z, 0.f, 1.f, tex},
(vertex_t){x + w, y + h, z, 1.f, 1.f, tex},
};
memmove(mlx->batch_vertices + mlx->batch_size, vertices, sizeof(vertices));
mlx->batch_size += 6;
Expand All @@ -84,81 +84,66 @@ void mlx_draw_instance(mlx_ctx_t* mlx, mlx_image_t* img, mlx_instance_t* instanc
mlx_flush_batch(mlx);
}

mlx_instance_t* mlx_grow_instances(mlx_image_t* img, bool* did_realloc)
static mlx_instance_t* mlx_grow_instances(mlx_image_t* img)
{
size_t new_size = 0;
mlx_image_ctx_t* const ctx = img->context;
if (img->count >= ctx->instances_capacity)
mlx_instance_t* temp = NULL;

// Do we need to grow ?
if (img->count + 1 >= ctx->instances_capacity)
{
if (ctx->instances_capacity == 0)
ctx->instances_capacity = img->count;
new_size++;
else
ctx->instances_capacity *= 2;
*did_realloc = true;
return realloc(img->instances, ctx->instances_capacity * sizeof(mlx_instance_t));
{
new_size = ctx->instances_capacity * 2;
}

if (!(temp = realloc(img->instances, new_size * sizeof(mlx_instance_t))))
return (NULL);
ctx->instances_capacity = new_size;
img->instances = temp;
}
*did_realloc = false;
return img->instances;
img->count++;
return (img->instances);
}

//= Public =//

void mlx_set_instance_depth(mlx_instance_t* instance, int32_t zdepth)
{
MLX_NONNULL(instance);

if (instance->z == zdepth)
return;
instance->z = zdepth;

/**
* NOTE: The reason why we don't sort directly is that
* the user might call this function multiple times in a row and we don't
* want to sort for every change. Pre-loop wise that is.
*/
sort_queue = true;
}

int32_t mlx_image_to_window(mlx_t* mlx, mlx_image_t* img, int32_t x, int32_t y)
{
MLX_NONNULL(mlx);
MLX_NONNULL(img);

// Allocate buffers...
img->count++;
bool did_realloc;
mlx_instance_t* instances = mlx_grow_instances(img, &did_realloc);
draw_queue_t* queue = calloc(1, sizeof(draw_queue_t));
if (!instances || !queue)
mlx_ctx_t* mlxctx = mlx->context;

// Grow instances to fit new instance.
mlx_instance_t* instances;

if (!(instances = mlx_grow_instances(img)))
{
if (did_realloc)
free(instances);
return (free(queue), mlx_error(MLX_MEMFAIL), -1);
mlx_error(MLX_MEMFAIL);
return (-1);
}

// Set data...
queue->image = img;
int32_t index = queue->instanceid = img->count - 1;
const int32_t index = img->count - 1;
img->instances = instances;
img->instances[index].x = x;
img->instances[index].y = y;

// NOTE: We keep updating the Z for the convenience of the user.
// Always update Z depth to prevent overlapping images by default.
img->instances[index].z = ((mlx_ctx_t*)mlx->context)->zdepth++;
img->instances[index].custom_depth = -1;
img->instances[index].enabled = true;

// Add draw call...
sort_queue = true;
mlx_list_t* templst;
if ((templst = mlx_lstnew(queue)))
{
mlx_lstadd_front(&((mlx_ctx_t*)mlx->context)->render_queue, templst);
return (index);
}
return (mlx_freen(2, instances, queue), mlx_error(MLX_MEMFAIL), -1);
// Add drawcall
draw_queue_t queue = (draw_queue_t){ img, img->count - 1, 0};
if (!mlx_vector_push_back(&(mlxctx->render_queue), &queue))
return (-1);

mlxctx->instance_count++;
return (index);
}

mlx_image_t* mlx_new_image(mlx_t* mlx, uint32_t width, uint32_t height)
mlx_image_t *mlx_new_image(mlx_t* mlx, uint32_t width, uint32_t height)
{
MLX_NONNULL(mlx);

Expand Down Expand Up @@ -209,9 +194,15 @@ void mlx_delete_image(mlx_t* mlx, mlx_image_t* image)
mlx_ctx_t* mlxctx = mlx->context;

// Delete all instances in the render queue
mlx_list_t* quelst;
while ((quelst = mlx_lstremove(&mlxctx->render_queue, image, &mlx_equal_inst)))
mlx_freen(2, quelst->content, quelst);
for(int32_t i = mlxctx->render_queue.count - 1; i >= 0 ; i--)
{
draw_queue_t* element = mlx_vector_get(&mlxctx->render_queue, i);

if (element->image == image)
mlx_vector_delete(&mlxctx->render_queue, i);
}

mlxctx->instance_count -= image->count;

mlx_list_t* imglst;
if ((imglst = mlx_lstremove(&mlxctx->images, image, &mlx_equal_image)))
Expand All @@ -221,6 +212,18 @@ void mlx_delete_image(mlx_t* mlx, mlx_image_t* image)
}
}

int32_t mlx_image_calculate_max_depth(mlx_image_t* image)
{
int32_t depth = 0;
for (int32_t i = 0; i < image->count; i++)
{
const mlx_instance_t* instance = &image->instances[i];
depth += instance->custom_depth > 0 ? instance->custom_depth : 1;
}

return depth;
}

bool mlx_resize_image(mlx_image_t* img, uint32_t nwidth, uint32_t nheight)
{
MLX_NONNULL(img);
Expand Down
1 change: 1 addition & 0 deletions src/mlx_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ mlx_t* mlx_init(int32_t width, int32_t height, const char* title, bool resize)
mlx->height = height;
mlxctx->initialWidth = width;
mlxctx->initialHeight = height;
mlx_vector_init(&mlxctx->render_queue, sizeof(draw_queue_t));

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
Expand Down
19 changes: 7 additions & 12 deletions src/mlx_loop.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,9 @@ static void mlx_render_images(mlx_t* mlx)
{
mlx_ctx_t* mlxctx = mlx->context;
mlx_list_t* imglst = mlxctx->images;

if (sort_queue)
{
sort_queue = false;
mlx_sort_renderqueue(&mlxctx->render_queue);
}
mlx_vec_t *render_queue = &mlxctx->render_queue;

mlx_render_queue_sort(render_queue);

// Upload image textures to GPU
while (imglst)
Expand All @@ -50,15 +47,13 @@ static void mlx_render_images(mlx_t* mlx)
}

// Execute draw calls
mlx_list_t* render_queue = mlxctx->render_queue;
while (render_queue)
for (int32_t i = 0; i < render_queue->count; i++)
{
draw_queue_t* drawcall = render_queue->content;
draw_queue_t* drawcall = mlx_vector_get(render_queue, i);
mlx_instance_t* instance = &drawcall->image->instances[drawcall->instanceid];

if (drawcall && drawcall->image->enabled && instance->enabled)
mlx_draw_instance(mlx->context, drawcall->image, instance);
render_queue = render_queue->next;
if (drawcall->image->enabled && instance->enabled)
mlx_draw_instance(mlx->context, drawcall->image, instance, drawcall->caluclatedDepth);
}
}

Expand Down
Loading