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:
Piotr Krygier
2026-03-19 21:00:39 +01:00
parent 984a56a8e8
commit 99fb36d9fd
14 changed files with 186 additions and 32 deletions
+129
View File
@@ -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)