Add basic loader for gltf
Added loading of avocado. Something is still wrong though, becaus I cannot see the seed. But basic functionality is there.
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 3.0 MiB |
@@ -10,13 +10,16 @@
|
||||
*/
|
||||
#include <SDL3/SDL_log.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#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)
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
+34
-19
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ project('RedScarfEngine',
|
||||
'werror=true'
|
||||
])
|
||||
|
||||
# add_project_arguments('-DWAYLAND=1', language : 'c')
|
||||
|
||||
subdir('utilities')
|
||||
subdir('graphics')
|
||||
subdir('events')
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#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 */
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user