From 9acc6b19c6efefb75ee5bc409df3e9346bd07d73 Mon Sep 17 00:00:00 2001 From: gramanas Date: Fri, 31 May 2024 22:44:35 +0300 Subject: Load glTF --- src/render.c | 260 ++++++++++++++++++++++------------------------------------- 1 file changed, 98 insertions(+), 162 deletions(-) (limited to 'src/render.c') diff --git a/src/render.c b/src/render.c index db3c168..275752c 100644 --- a/src/render.c +++ b/src/render.c @@ -39,7 +39,7 @@ #define TEXTURE_PATH "assets/viking_room.png" void load_model_obj(); - +void load_model_gltf(); // embedded clgm library uint32_t currentFrame = 0; state_t s; @@ -962,7 +962,7 @@ vulkan_create_graphics_pipeline(VkPolygonMode polygon_mode) attributeDescriptions[1].binding = 0; attributeDescriptions[1].location = 1; attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; - attributeDescriptions[1].offset = offsetof(Vertex, color); + attributeDescriptions[1].offset = offsetof(Vertex, normal); attributeDescriptions[2].binding = 0; attributeDescriptions[2].location = 2; @@ -1494,6 +1494,8 @@ int polygon_mode_n = 3; VkPolygonMode polygon_modes[3] = {VK_POLYGON_MODE_FILL, VK_POLYGON_MODE_LINE, VK_POLYGON_MODE_POINT}; +int toggle = 0; + void handle_input(bool * quit) { @@ -1548,13 +1550,21 @@ handle_input(bool * quit) vkDeviceWaitIdle(s.vk_device); free(s.vertices); free(s.indices); - if (!strcmp(s.model_path, "assets/human.obj")) - strcpy(s.model_path, "assets/viking_room.obj"); - else if (!strcmp(s.model_path, "assets/viking_room.obj")) - strcpy(s.model_path, "assets/test.obj"); - else - strcpy(s.model_path, "assets/human.obj"); - load_model_obj(); + /* if (!strcmp(s.model_path, "assets/human.obj")) */ + /* strcpy(s.model_path, "assets/viking_room.obj"); */ + /* else if (!strcmp(s.model_path, "assets/viking_room.obj")) */ + /* strcpy(s.model_path, "assets/monkey.obj"); */ + /* else */ + /* strcpy(s.model_path, "assets/human.obj"); */ + + if (toggle) { + strcpy(s.model_path, "assets/monkey.obj"); + load_model_obj(); + toggle = 0; + } else { + toggle = 1; + load_model_gltf(); + } vkDestroyBuffer(s.vk_device, s.vk_vertex_buffer, NULL); vkFreeMemory(s.vk_device, s.vk_vertex_buffer_memory, NULL); @@ -1825,6 +1835,7 @@ load_model_obj() indexed draw call. */ + s.vertices = (Vertex *)malloc(s.indices_count * sizeof(Vertex)); /* Count indexs and vertices */ size_t c = 0; for (size_t ii = 0; ii < m->group_count; ii++) { @@ -1833,6 +1844,7 @@ load_model_obj() unsigned int fv = m->face_vertices[grp->face_offset + jj]; for (unsigned int kk = 0; kk < fv; kk++) { /* position index */ + fastObjIndex mi = m->indices[grp->index_offset + c]; uint32_t mip = m->indices[grp->index_offset + c].p - 1; /* make index start from zero */ /* flag if we've seen the index*/ @@ -1844,51 +1856,8 @@ load_model_obj() } } s.indices[c] = mip; + if (!index_seen) { - /* If not seen, incremet vertices */ - s.vertices_count++; - } - c++; - } - } - } - - printf("vertex count %ld!!!!!!!!!!!!!!!!!!\n", s.vertices_count); - s.vertices = (Vertex *)malloc(s.vertices_count * sizeof(Vertex)); - - /* for (size_t i = 0; i < s.indices_count; i++) { */ - /* uint32_t mip = s.indices[i]; */ - /* int index_seen = 0; */ - /* for (size_t j = 0; j < i; j++) { */ - /* if (mip == s.indices[j]) { */ - /* index_seen = 1; */ - /* break; */ - /* } */ - /* } */ - /* if (!index_seen) { */ - /* s.vertices[mip].pos.x = m->positions[3 * (mip + 1) + 0]; */ - /* s.vertices[mip].pos.y = m->positions[3 * (mip + 1) + 1]; */ - /* s.vertices[mip].pos.z = m->positions[3 * (mip + 1) + 2]; */ - /* } */ - /* } */ - - for (size_t ii = 0; ii < m->group_count; ii++) { - const fastObjGroup *grp = &m->groups[ii]; - size_t idx = 0; - for (unsigned int jj = 0; jj < grp->face_count; jj++) { - unsigned int fv = m->face_vertices[grp->face_offset + jj]; - for (unsigned int kk = 0; kk < fv; kk++) { - fastObjIndex mi = m->indices[grp->index_offset + idx]; - - int flag = 0; - for (size_t i = 0; i < idx; i++) { - /* if it exists */ - if (mi.p - 1 == s.indices[i]) { - flag = 1; - break; - } - } - if (!flag) { int index = mi.p - 1; /* zero indexed */ if (mi.p) { s.vertices[index].pos.x = m->positions[3 * mi.p + 0]; @@ -1900,130 +1869,97 @@ load_model_obj() s.vertices[index].texCoord.y = 1.0f - m->texcoords[2 * mi.t + 1]; } if (mi.n) { - s.vertices[index].color.x = m->normals[3 * mi.n + 0]; - s.vertices[index].color.y = m->normals[3 * mi.n + 1]; - s.vertices[index].color.z = m->normals[3 * mi.n + 2]; + s.vertices[index].normal.x = m->normals[3 * mi.n + 0]; + s.vertices[index].normal.y = m->normals[3 * mi.n + 1]; + s.vertices[index].normal.z = m->normals[3 * mi.n + 2]; } + + /* If not seen, incremet vertices */ + s.vertices_count++; } - idx++; + c++; } } } - + + vk_log(VK_INFO, "[obj] %s: Loaded %ld vertices %ld indices\n", s.model_path, s.vertices_count, s.indices_count); + + fast_obj_destroy(m); } void load_model_gltf() { // TODO maybe copy the raylib implemenetation - /* - RESTRICTIONS: - - Only triangle meshes supported - - Vertex attribute types and formats supported: - > Vertices (position): vec3: float - > Normals: vec3: float - > Texcoords: vec2: float - > Colors: vec4: u8, u16, f32 (normalized) - > Indices: u16, u32 (truncated to u16) - - Node hierarchies or transforms not supported - */ - /* cgltf_options options; */ - /* memset(&options, 0, sizeof(cgltf_options)); */ - /* cgltf_data* data = NULL; */ - /* cgltf_result result = cgltf_parse_file(&options, MODEL_PATH, &data); */ + char * path = "assets/monkey.glb"; + cgltf_options options; + memset(&options, 0, sizeof(cgltf_options)); + cgltf_data* data = NULL; + cgltf_result result = cgltf_parse_file(&options, path, &data); - /* if (result == cgltf_result_success) */ - /* result = cgltf_load_buffers(&options, data, MODEL_PATH); */ + if (result == cgltf_result_success) + result = cgltf_load_buffers(&options, data, path); + else { + vk_log(VK_ERROR, "Can't load %s\n", path); + } - /* if (result == cgltf_result_success) */ - /* result = cgltf_validate(data); */ + if (result == cgltf_result_success) + result = cgltf_validate(data); - /* if (data->meshes_count < 1) { */ - /* cgltf_free(data); */ - /* return; */ - /* } */ + if (data->meshes_count < 1) { + cgltf_free(data); + return; + } - /* int idx = 0; */ - /* int meshIndex = 0; */ - /* for (unsigned int i = 0, meshIndex = 0; i < data->meshes_count; i++) { */ - /* for (unsigned int p = 0; p < data->meshes[i].primitives_count; p++) { */ - /* // NOTE: We only support primitives defined by triangles */ - /* // Other alternatives: points, lines, line_strip, triangle_strip */ - /* if (data->meshes[i].primitives[p].type != cgltf_primitive_type_triangles) continue; */ - - /* // NOTE: Attributes data could be provided in several data formats (8, 8u, 16u, 32...), */ - /* // Only some formats for each attribute type are supported, read info at the top of this function! */ - - /* for (unsigned int j = 0; j < data->meshes[i].primitives[p].attributes_count; j++) { */ - /* // Check the different attributes for every primitive */ - /* if (data->meshes[i].primitives[p].attributes[j].type == cgltf_attribute_type_position) { // POSITION, vec3, float */ - /* cgltf_accessor *attribute = data->meshes[i].primitives[p].attributes[j].data; */ - - /* // WARNING: SPECS: POSITION accessor MUST have its min and max properties defined */ - - /* if ((attribute->type == cgltf_type_vec3) && (attribute->component_type == cgltf_component_type_r_32f)) { */ - /* // Init raylib mesh vertices to copy glTF attribute data */ - /* s.vertices_count = attribute->count / 3; */ - /* s.vertices = calloc(attribute->count, attribute->count*sizeof(Vertex)); */ - - /* size_t float_count = cgltf_accessor_unpack_floats(attribute, NULL, 0); */ - /* printf("This many floats: %ld\n", float_count); */ - /* float floats[float_count] = {}; */ - /* cgltf_accessor_unpack_floats(attribute, floats, float_count); */ - - /* for (unsigned int k = 0; k < attribute->count + 3; k+=3) { */ - /* s.vertices[idx].pos.x = floats[k + 0]; */ - /* s.vertices[idx].pos.y = floats[k + 1]; */ - /* s.vertices[idx].pos.z = floats[k + 2]; */ - /* //s.indices[idx] = idx; */ - /* idx++; */ - /* } */ - /* // Load 3 components of float data type into mesh.vertices */ - /* } */ - /* } */ - /* } */ - /* if (data->meshes[i].primitives[p].indices != NULL) { */ - /* printf("THERE ARE INDIXCES!!!\n"); */ - /* cgltf_accessor *attribute = data->meshes[i].primitives[p].indices; */ - - /* s.indices_count = attribute->count / 3; */ - /* s.indices = calloc(attribute->count, attribute->count*sizeof(uint32_t)); */ - - /* if (attribute->component_type == cgltf_component_type_r_16u) { */ - /* size_t float_count = cgltf_accessor_unpack_indices(attribute, NULL, 0, 0); */ - /* printf("This many floats: %ld\n", float_count); */ - /* uint16_t floats[float_count] = {}; */ - /* cgltf_accessor_unpack_indices(attribute, floats, float_count, */ - /* float_count); */ - - /* for (int x = 0; x < float_count; x++) { */ - /* printf("%d \n", floats[x]); */ - /* } */ - - /* } */ - /* else if (attribute->component_type == cgltf_component_type_r_32u) { */ - /* printf("ASDASDASDAS2222222!\n"); */ - /* // Init raylib mesh indices to copy glTF attribute data */ - /* /\* model.meshes[meshIndex].indices = RL_MALLOC(attribute->count*sizeof(unsigned short)); *\/ */ - - /* /\* // Load data into a temp buffer to be converted to raylib data type *\/ */ - /* /\* unsigned int *temp = malloc(attribute->count*sizeof(unsigned int)); *\/ */ - /* /\* LOAD_ATTRIBUTE(attribute, 1, unsigned int, temp); *\/ */ - - /* /\* // Convert data to raylib indices data type (unsigned short) *\/ */ - /* /\* for (unsigned int d = 0; d < attribute->count; d++) model.meshes[meshIndex].indices[d] = (unsigned short)temp[d]; *\/ */ - - /* //free(temp); */ - /* } */ - /* } */ - /* } */ - /* } */ + for (cgltf_size i = 0; i < data->meshes_count; ++i) { + cgltf_mesh *mesh = &data->meshes[i]; + for (cgltf_size j = 0; j < mesh->primitives_count; ++j) { + cgltf_primitive* primitive = &mesh->primitives[j]; - /* for (int i = 0; i < s.vertices_count; i++) { */ - /* printf("%d: %f %f %f\n",i, s.vertices[i].pos.x, s.vertices[i].pos.y, s.vertices[i].pos.z); */ - /* } */ + cgltf_accessor* index_accessor = primitive->indices; + + if (index_accessor) { + s.indices_count = index_accessor->count; + s.indices = (uint32_t *)malloc(s.indices_count * sizeof(uint32_t)); + // Read indices + for (cgltf_size k = 0; k < index_accessor->count; ++k) { + s.indices[k] = cgltf_accessor_read_index(index_accessor, k); + } + } + + // Find the position attribute accessor + for (cgltf_size k = 0; k < primitive->attributes_count; ++k) { + if (primitive->attributes[k].type == cgltf_attribute_type_position) { + cgltf_accessor* position_accessor = primitive->attributes[k].data; + s.vertices_count = position_accessor->count; + s.vertices = (Vertex *)malloc(s.vertices_count * sizeof(Vertex)); + // Read vertex positions + for (cgltf_size k = 0; k < position_accessor->count; ++k) { + float vertex[3]; + cgltf_accessor_read_float(position_accessor, k, (cgltf_float *)(&s.vertices[k].pos), 3); + } + } + if (primitive->attributes[k].type == cgltf_attribute_type_texcoord) { + cgltf_accessor* texcoord_accessor = primitive->attributes[k].data; + // Read texture coordinates + for (cgltf_size k = 0; k < texcoord_accessor->count; ++k) { + cgltf_accessor_read_float(texcoord_accessor, k, (cgltf_float *)(&s.vertices[k].texCoord), 2); + } + } + if (primitive->attributes[k].type == cgltf_attribute_type_normal) { + cgltf_accessor* color_accessor = primitive->attributes[k].data; + // Read texture coordinates + for (cgltf_size k = 0; k < color_accessor->count; ++k) { + cgltf_accessor_read_float(color_accessor, k, (cgltf_float *)(&s.vertices[k].normal), 3); + } + } + } + } + } + + vk_log(VK_INFO, "[glTF] %s: Loaded %ld vertices %ld indices\n", path, s.vertices_count, s.indices_count); - /* cgltf_free(data); */ + cgltf_free(data); } void @@ -2050,8 +1986,8 @@ init_vulkan() vulkan_create_texture_image(); vulkan_create_texture_image_view(); vulkan_create_texture_sampler(); - load_model_obj(); - //load_model_gltf(); + //load_model_obj(); + load_model_gltf(); vulkan_create_vertex_buffer(); vulkan_create_index_buffer(); vulkan_create_uniform_buffers(); -- cgit v1.2.3