Skip to content

Commit

Permalink
Merge pull request #54 from codam-coding-college/fix-depth
Browse files Browse the repository at this point in the history
Fix images not appearing
  • Loading branch information
W2Wizard authored Aug 27, 2022
2 parents 266b2af + 9552fc1 commit a1d9df1
Show file tree
Hide file tree
Showing 11 changed files with 313 additions and 164 deletions.
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

0 comments on commit a1d9df1

Please sign in to comment.