diff --git a/Avocado_baseColor.png b/Avocado_baseColor.png new file mode 100644 index 00000000..38630edf Binary files /dev/null and b/Avocado_baseColor.png differ diff --git a/graphics/src/mesh_controller.c b/graphics/src/mesh_controller.c index 03136b0a..d210a8cb 100644 --- a/graphics/src/mesh_controller.c +++ b/graphics/src/mesh_controller.c @@ -10,13 +10,16 @@ */ #include #include +#include #include #include "src/graphics_context.h" #include "src/vulkan_commons.h" +#include "utilities/cgltf.h" #include "utilities/commons.h" #include "utilities/entity.h" #include "utilities/errors_common.h" +#include "utilities/file_utils.h" #include "vulkan_buffers.h" rse_err_t mesh_create(struct graphics_context_t* context, @@ -46,6 +49,132 @@ rse_err_t mesh_create(struct graphics_context_t* context, return status; } +rse_err_t mesh_create_from_file(struct graphics_context_t* context, const char* file_name, rse_id_t* mesh_id) +{ + struct vertex_t* vertices = NULL; + uint16_t* indices = NULL; + size_t indices_count = 0U; + size_t mesh_index = 0U; + size_t primitive_index = 0U; + size_t attribute_index = 0U; + cgltf_mesh* mesh = NULL; + cgltf_primitive* primitive = NULL; + cgltf_attribute* attribute = NULL; + size_t* position_data_offset = NULL; + size_t* color_data_offset = NULL; + size_t* texture_coord_data_offset = NULL; + size_t* indices_data_offset = 0U; + size_t data_count = 0U; + size_t data_index = 0U; + size_t tmp_offset = 0U; + uint8_t* bin = NULL; + + (void)context; + (void)mesh_id; + + cgltf_data* data = NULL; + rse_err_t status = RSE_ERROR_NO_ERROR; + + STATUS_CHECK(file_load_gltf(file_name, &data)); + + SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Attribute name: %s", data->meshes->primitives[0].attributes[3].name); + SDL_LogInfo(SDL_LOG_CATEGORY_GPU, "Accessor: %ld", data->meshes->primitives[0].attributes[3].data->count); + + for (mesh_index = 0U; mesh_index < data->meshes_count; ++mesh_index) { + mesh = &data->meshes[mesh_index]; + + for (primitive_index = 0U; primitive_index < mesh->primitives_count; ++primitive_index) { + primitive = &mesh->primitives[primitive_index]; + + for (attribute_index = 0; attribute_index < primitive->attributes_count; ++attribute_index) { + attribute = &primitive->attributes[attribute_index]; + + if (primitive->indices == NULL) { + SDL_LogCritical(SDL_LOG_CATEGORY_GPU, + "No indices for mesh found. Currently only indexed drawing is supported"); + return RSE_ERROR_INVALID_PARAM; + } else { + rse_malloc(indices_data_offset, sizeof(size_t)); + *indices_data_offset = primitive->indices->buffer_view->offset; + indices_count = primitive->indices->count; + rse_malloc(indices, (sizeof(uint16_t) * indices_count)); + } + + tmp_offset = attribute->data->buffer_view->offset; + + switch (attribute->type) { + case cgltf_attribute_type_position: + rse_malloc(position_data_offset, sizeof(size_t)); + *position_data_offset = tmp_offset; + data_count = attribute->data->count; + break; + case cgltf_attribute_type_color: + rse_malloc(color_data_offset, sizeof(size_t)); + *color_data_offset = tmp_offset; + break; + case cgltf_attribute_type_texcoord: + rse_malloc(texture_coord_data_offset, sizeof(size_t)); + *texture_coord_data_offset = tmp_offset; + break; + default: + break; + } + } + } + + if (position_data_offset == NULL) { + SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to retrieve position data for mesh %s", file_name); + status = RSE_ERROR_INVALID_PARAM; + + goto exit; + } + + if (data_count == 0) { + SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failure: data count for mesh is 0"); + status = RSE_ERROR_INVALID_PARAM; + + goto exit; + } + + rse_malloc(vertices, sizeof(struct vertex_t) * data_count); + bin = (uint8_t*)data->bin; + + for (data_index = 0U; data_index < data_count; ++data_index) { + rse_memcpy(vertices[data_index].pos, + (bin + *position_data_offset + (sizeof(vec3) * data_index)), + sizeof(vec3)); + if (color_data_offset != NULL) { + rse_memcpy(vertices[data_index].color, + (bin + *color_data_offset + (sizeof(vec3) * data_index)), + sizeof(vec3)); + } else { + vertices[data_index].color[0] = 1.0; + vertices[data_index].color[1] = 1.0; + vertices[data_index].color[2] = 1.0; + } + + if (texture_coord_data_offset != NULL) { + rse_memcpy(vertices[data_index].tex_coords, + (bin + *texture_coord_data_offset + (sizeof(vec2) * data_index)), + sizeof(vec2)); + } + } + + rse_memcpy(indices, (bin + *indices_data_offset), (sizeof(uint16_t) * indices_count)); + + STATUS_CHECK(mesh_create(context, vertices, indices, data_count, indices_count, mesh_id)); + } + +exit: + rse_free(position_data_offset); + rse_free(color_data_offset); + rse_free(texture_coord_data_offset); + rse_free(vertices); + cgltf_free(data); + + return status; +} + rse_err_t mesh_create_instance(struct graphics_context_t* context, entity_t entity, struct instance_data_t instance_data) diff --git a/graphics/src/mesh_controller.h b/graphics/src/mesh_controller.h index 87c1a470..9f139873 100644 --- a/graphics/src/mesh_controller.h +++ b/graphics/src/mesh_controller.h @@ -41,6 +41,7 @@ rse_err_t mesh_create(struct graphics_context_t* context, struct vertex_t* verti rse_err_t mesh_create_instance(struct graphics_context_t* context, entity_t entity, struct instance_data_t instance_data); +rse_err_t mesh_create_from_file(struct graphics_context_t* context, const char* file_name, rse_id_t* mesh_id); /** * @brief Get the vertex count for mesh with mesh_id ID * diff --git a/graphics/src/pipeline_builder.c b/graphics/src/pipeline_builder.c index 247d14aa..99911c52 100644 --- a/graphics/src/pipeline_builder.c +++ b/graphics/src/pipeline_builder.c @@ -124,7 +124,7 @@ static rse_err_t pipeline_add_rasterizer(struct pipeline_t* pipeline) pipeline->rasterizer.rasterizerDiscardEnable = VK_FALSE; /* Disable/Enable output to framebuffer*/ pipeline->rasterizer.polygonMode = VK_POLYGON_MODE_FILL; pipeline->rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - pipeline->rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; + pipeline->rasterizer.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; pipeline->rasterizer.depthBiasEnable = VK_FALSE; pipeline->rasterizer.depthBiasConstantFactor = 0.0f; pipeline->rasterizer.depthBiasClamp = 0.0f; diff --git a/graphics/src/rse_graphics.c b/graphics/src/rse_graphics.c index 8fb1c680..ae38be1c 100644 --- a/graphics/src/rse_graphics.c +++ b/graphics/src/rse_graphics.c @@ -116,7 +116,7 @@ rse_err_t rse_graphics_init(struct graphics_context_t* context) return status; } -#define TEXTURES_COUNT (2U) +#define TEXTURES_COUNT (3U) rse_err_t rse_graphics_test_function(struct graphics_context_t* context) { rse_err_t status = RSE_ERROR_NO_ERROR; @@ -125,28 +125,35 @@ rse_err_t rse_graphics_test_function(struct graphics_context_t* context) rse_id_t descriptor_set_handle = 0; struct descriptor_set_layout_bindings_t layout_bindings = {0}; struct pipeline_infos_t pipeline_infos = {0}; - rse_id_t mesh_id_1, mesh_id_2 = 0; - rse_id_t font_id = 0; + rse_id_t mesh_id_1 = 0; + rse_id_t mesh_id_2 = 0; + rse_id_t avocado_id = 0; + // rse_id_t font_id = 0; rse_id_t static_mesh_renderer = 0U; rse_id_t vertex_shader_id, fragment_shader_id; STATUS_CHECK(texture_load_from_file(context, "../../test_image.jpg", &textures[0])); STATUS_CHECK(texture_load_from_file(context, "../../test_image_2.jpg", &textures[1])); + STATUS_CHECK(texture_load_from_file(context, "../../Avocado_baseColor.png", &textures[2])); - STATUS_CHECK(fonts_init()); - STATUS_CHECK(fonts_load_from_file(context, "../../NotoSansMono-Regular.ttf", &font_id)); - STATUS_CHECK(fonts_set_font_size(context, font_id, 16)); + // STATUS_CHECK(fonts_init()); + // STATUS_CHECK(fonts_load_from_file(context, "../../NotoSansMono-Regular.ttf", &font_id)); + // STATUS_CHECK(fonts_set_font_size(context, font_id, 16)); // FIXME: Temporary array of vertices, for testing purposes - struct vertex_t vertices[] = {{{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}, - {{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}, - {{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}}, - {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}}; + struct vertex_t vertices[] = { + {{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}, + {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}, + {{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}}, + {{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}, + }; - struct vertex_t vertices2[] = {{{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}, - {{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}, - {{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}}, - {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}}; + struct vertex_t vertices_2[] = { + {{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}, + {{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}}, + {{0.2f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}}, + {{0.2f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}}, + }; // FIXME: Temporary array of vertices, for testing purposes uint16_t indices[] = {0, 1, 2, 2, 3, 0}; @@ -155,7 +162,7 @@ rse_err_t rse_graphics_test_function(struct graphics_context_t* context) if (RSE_ERROR_NO_ERROR != mesh_create_instance(context, mesh_id_1, - (struct instance_data_t){{0.0f, 0.0f, 2.4f}, {0.0f, 0.0f, 0.0}, 1.0f, textures[1]})) { + (struct instance_data_t){{0.0f, 1.0f, 0.0f}, {0.0f, 0.0f, 0.0}, 1.0f, textures[0]})) { exit(1); } @@ -163,17 +170,25 @@ rse_err_t rse_graphics_test_function(struct graphics_context_t* context) mesh_create_instance( context, mesh_id_1, - (struct instance_data_t){{-0.5f, 0.0f, -1.0f}, {0.0f, 0.0f, glm_rad(10.0f)}, 1.0f, textures[0]})) { + (struct instance_data_t){{-0.5f, 0.0f, -1.0f}, {0.0f, 0.0f, glm_rad(10.0f)}, 1.0f, textures[1]})) { exit(1); } - STATUS_CHECK(mesh_create(context, vertices2, indices, 4, 6, &mesh_id_2)); - + STATUS_CHECK(mesh_create(context, vertices_2, indices, 4, 6, &mesh_id_2)); if (RSE_ERROR_NO_ERROR != mesh_create_instance( context, mesh_id_2, - (struct instance_data_t){{1.0f, 1.0f, 0.0f}, {0.0f, 0.0f, glm_rad(0.0f)}, 1.0f, textures[0]})) { + (struct instance_data_t){{0.5f, 0.0f, -1.0f}, {0.0f, 0.0f, glm_rad(0.0f)}, 1.0f, textures[1]})) { + exit(1); + } + + mesh_create_from_file(context, "../../Avocado.glb", &avocado_id); + if (RSE_ERROR_NO_ERROR != + mesh_create_instance( + context, + avocado_id, + (struct instance_data_t){{0.0f, 0.0f, -4.0f}, {0.0f, glm_rad(130.0f), 0.0f}, 2.0f, textures[2]})) { exit(1); } diff --git a/graphics/src/vulkan_buffers.c b/graphics/src/vulkan_buffers.c index 88968274..26a00816 100644 --- a/graphics/src/vulkan_buffers.c +++ b/graphics/src/vulkan_buffers.c @@ -210,8 +210,11 @@ rse_err_t add_vertices(struct graphics_context_t* context, size_t vertices_count, const struct vertex_t* vertices, size_t indices_count, - const uint16_t* indices) + uint16_t* indices) { + // static uint16_t last_index = 0U; + // uint16_t max_index = 0U; + // size_t idx = 0U; rse_err_t status = RSE_ERROR_NO_ERROR; struct vulkan_buffer_t staging_buffer; size_t vertices_size = sizeof(vertices[0]) * vertices_count; @@ -235,6 +238,7 @@ rse_err_t add_vertices(struct graphics_context_t* context, copy_buffer(context, staging_buffer.buffer, vertex_buffer->buffer, vertices_size, vertex_buffer->allocated_size); vertex_buffer->allocated_size += vertices_size; + /* Fill staging buffer with index data */ memcpy(staging_buffer.allocation_info.pMappedData, indices, indices_size); copy_buffer(context, staging_buffer.buffer, index_buffer->buffer, indices_size, index_buffer->allocated_size); @@ -274,6 +278,7 @@ rse_err_t buffers_update(struct graphics_context_t* context) sizeof(VkDrawIndexedIndirectCommand) * context->mesh_data.mesh_count; struct vulkan_buffer_t staging_buffer; struct mesh_t* mesh = NULL; + uint32_t indices_count = 0U; rse_malloc(draw_indirect_commands_buffer, draw_indirect_commands_buffer_size); for (iter = 0U; iter < context->mesh_data.mesh_count; ++iter) { @@ -295,13 +300,14 @@ rse_err_t buffers_update(struct graphics_context_t* context) draw_indirect_command->firstInstance = 0; draw_indirect_command->vertexOffset = 0; } else { - draw_indirect_command->firstIndex = context->mesh_data.mesh_bucket[iter - 1].index_count; + draw_indirect_command->firstIndex = indices_count; draw_indirect_command->firstInstance = draw_indirect_commands_buffer[iter - 1].firstInstance + draw_indirect_commands_buffer[iter - 1].instanceCount; - draw_indirect_command->vertexOffset = (context->mesh_data.mesh_bucket[iter - 1].vertex_count); + draw_indirect_command->vertexOffset = (context->mesh_data.mesh_bucket[iter - 1].vertex_count + draw_indirect_commands_buffer[iter-1].vertexOffset); } draw_indirect_command->indexCount = mesh->index_count; draw_indirect_command->instanceCount = mesh->instances_count; + indices_count += mesh->index_count; } /* Copy Draw indirect commands into buffer */ diff --git a/graphics/src/vulkan_buffers.h b/graphics/src/vulkan_buffers.h index 4a53d7f5..a2e983e0 100644 --- a/graphics/src/vulkan_buffers.h +++ b/graphics/src/vulkan_buffers.h @@ -36,7 +36,7 @@ rse_err_t buffer_create_uniform(struct graphics_context_t* context, struct vulka * @return rse_err_t RSE_ERROR_NO_ERROR on success */ rse_err_t add_vertices(struct graphics_context_t* context, uint16_t mesh_id, size_t vertices_count, - const struct vertex_t* vertices, size_t indices_count, const uint16_t* indices); + const struct vertex_t* vertices, size_t indices_count, uint16_t* indices); /** * @brief Add instance data to vulkan buffers diff --git a/graphics/src/window.c b/graphics/src/window.c index c8112f04..610d2b5f 100644 --- a/graphics/src/window.c +++ b/graphics/src/window.c @@ -30,7 +30,7 @@ rse_err_t window_init(SDL_Window** window_handle, bool* is_framebuffer_resized) *window_handle = SDL_CreateWindow("RedScarfEngine", 1024, 768, SDL_WINDOW_VULKAN); if (NULL == *window_handle) { - SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Window context creation failed"); + SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Window context creation failed. Reason: %s", SDL_GetError()); return RSE_ERROR_INTERNAL_ERROR; } diff --git a/meson.build b/meson.build index 803f11ae..d32e9a96 100644 --- a/meson.build +++ b/meson.build @@ -6,6 +6,8 @@ project('RedScarfEngine', 'werror=true' ]) +# add_project_arguments('-DWAYLAND=1', language : 'c') + subdir('utilities') subdir('graphics') subdir('events') diff --git a/red_scarf_engine/src/main.c b/red_scarf_engine/src/main.c index d3f27a1e..5659bb23 100644 --- a/red_scarf_engine/src/main.c +++ b/red_scarf_engine/src/main.c @@ -1,5 +1,7 @@ #include "red_scarf_engine.h" +#include "utilities/commons.h" #include "utilities/errors_common.h" +#include "graphics/src/mesh_controller.h" int main(int argc, char** argv) { diff --git a/utilities/cgltf.h b/utilities/cgltf.h index 316a11df..e09db930 100644 --- a/utilities/cgltf.h +++ b/utilities/cgltf.h @@ -4382,7 +4382,7 @@ static int cgltf_parse_json_diffuse_transmission(cgltf_options* options, jsmntok // Defaults cgltf_fill_float_array(out_diff_transmission->diffuse_transmission_color_factor, 3, 1.0f); out_diff_transmission->diffuse_transmission_factor = 0.f; - + for (int j = 0; j < size; ++j) { CGLTF_CHECK_KEY(tokens[i]); diff --git a/utilities/commons.h b/utilities/commons.h index f3dfe427..62b9adcb 100644 --- a/utilities/commons.h +++ b/utilities/commons.h @@ -28,7 +28,7 @@ exit(1); \ } -#define rse_free(ptr) free(ptr); +#define rse_free(ptr) if (ptr != NULL) free(ptr); #define rse_memcpy(dst, src, size) memcpy(dst, src, size); #define rse_memset(ptr, value, size) memset(ptr, value, size); diff --git a/utilities/file_utils.h b/utilities/file_utils.h index d734a21e..c233f2de 100644 --- a/utilities/file_utils.h +++ b/utilities/file_utils.h @@ -3,6 +3,7 @@ #include #include "commons.h" +#include "cgltf.h" #define MAX_PATH_LENGTH (4096U) @@ -22,7 +23,7 @@ rse_err_t file_load_pixels(const char* file_name, unsigned char* buffer, size_t* rse_err_t file_append_full_path(char* file_path, size_t max_buffer_size); -rse_err_t file_json_parser(const char* file_name); +rse_err_t file_load_gltf(const char* file_name, cgltf_data** data); #endif /* FILE_UTILS_H */ diff --git a/utilities/src/file_utils.c b/utilities/src/file_utils.c index 32dc9e28..a24a90e8 100644 --- a/utilities/src/file_utils.c +++ b/utilities/src/file_utils.c @@ -247,24 +247,22 @@ rse_err_t file_write(const char* file_name, size_t bytes_count, char* buffer) return ret; } -rse_err_t file_load_gltf(const char* file_name) +rse_err_t file_load_gltf(const char* file_name, cgltf_data** data) { char real_path[MAX_PATH_LENGTH] = {0}; rse_err_t ret = RSE_ERROR_NO_ERROR; cgltf_options options = {0}; - cgltf_data* data = NULL; strncpy(real_path, file_name, MAX_PATH_LENGTH); if ((ret = file_append_full_path(real_path, MAX_PATH_LENGTH)) != RSE_ERROR_NO_ERROR) { return ret; } - if (cgltf_parse_file(&options, real_path, &data) != cgltf_result_success) { + if (cgltf_parse_file(&options, real_path, data) != cgltf_result_success) { SDL_LogCritical(SDL_LOG_CATEGORY_APPLICATION, "Failed to parse GLTF data"); return RSE_ERROR_INTERNAL_ERROR; } - cgltf_free(data); return ret; }