diff options
author | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-10-05 12:48:05 +1000 |
---|---|---|
committer | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-10-05 12:48:05 +1000 |
commit | dfb6adbcbcc7d50b770b6d5ea82efdd8f8c32e25 (patch) | |
tree | a470b91a90716d7ea46fde53ed395449c24583a2 /src/resources/gltf.c | |
parent | 54354e32c6498cc7f8839ab4deb1208d37216cc5 (diff) |
delete documentation workflow
Diffstat (limited to 'src/resources/gltf.c')
-rw-r--r-- | src/resources/gltf.c | 596 |
1 files changed, 0 insertions, 596 deletions
diff --git a/src/resources/gltf.c b/src/resources/gltf.c deleted file mode 100644 index 66ae1b6..0000000 --- a/src/resources/gltf.c +++ /dev/null @@ -1,596 +0,0 @@ -#include <assert.h> -#include <stdlib.h> -#include <string.h> -#include "animation.h" -#include "colours.h" -#include "core.h" -#include "defines.h" -#include "file.h" -#include "loaders.h" -#include "log.h" -#include "maths.h" -#include "maths_types.h" -#include "mem.h" -#include "pbr.h" -#include "platform.h" -#include "ral_types.h" -#include "render.h" -#include "render_types.h" -#include "str.h" - -#define CGLTF_IMPLEMENTATION -#include <cgltf.h> - -extern Core g_core; - -/* GLTF Loading Pipeline - ===================== */ - -struct face { - cgltf_uint indices[3]; -}; -typedef struct face face; - -KITC_DECL_TYPED_ARRAY(Vec3) -KITC_DECL_TYPED_ARRAY(Vec2) -KITC_DECL_TYPED_ARRAY(Vec4u) -KITC_DECL_TYPED_ARRAY(Vec4i) -KITC_DECL_TYPED_ARRAY(Vec4) -KITC_DECL_TYPED_ARRAY(face) -KITC_DECL_TYPED_ARRAY(i32) - -size_t GLTF_LoadMaterials(cgltf_data* data, Str8 relative_path, Material_darray* out_materials); - -ModelHandle ModelLoad_gltf(const char* path, bool invert_texture_y) { - size_t arena_size = MB(1); - arena scratch = arena_create(malloc(arena_size), arena_size); - - TRACE("Loading model at Path %s\n", path); - path_opt relative_path = path_parent(&scratch, path); - if (!relative_path.has_value) { - WARN("Couldnt get a relative path for the path to use for loading materials & textures later"); - } - const char* file_string = string_from_file(path); - - ModelHandle handle; - Model* model = Model_pool_alloc(&g_core.models, &handle); - model->name = Str8_cstr_view(path); - - bool success = - model_load_gltf_str(file_string, path, relative_path.path, model, invert_texture_y); - - if (!success) { - FATAL("Couldnt load GLTF file at path %s", path); - ERROR_EXIT("Load fails are considered crash-worthy right now. This will change later.\n"); - } - - arena_free_all(&scratch); - arena_free_storage(&scratch); - return handle; -} - -void assert_path_type_matches_component_type(cgltf_animation_path_type target_path, - cgltf_accessor* output) { - if (target_path == cgltf_animation_path_type_rotation) { - assert(output->component_type == cgltf_component_type_r_32f); - assert(output->type == cgltf_type_vec4); - } -} - -// TODO: Brainstorm how I can make this simpler and break it up into more testable pieces - -void load_position_components(Vec3_darray* positions, cgltf_accessor* accessor) { - TRACE("Loading %d vec3 position components", accessor->count); - CASSERT_MSG(accessor->component_type == cgltf_component_type_r_32f, - "Positions components are floats"); - CASSERT_MSG(accessor->type == cgltf_type_vec3, "Vertex positions should be a vec3"); - - for (cgltf_size v = 0; v < accessor->count; ++v) { - Vec3 pos; - cgltf_accessor_read_float(accessor, v, &pos.x, 3); - Vec3_darray_push(positions, pos); - } -} - -void load_normal_components(Vec3_darray* normals, cgltf_accessor* accessor) { - TRACE("Loading %d vec3 normal components", accessor->count); - CASSERT_MSG(accessor->component_type == cgltf_component_type_r_32f, - "Normal vector components are floats"); - CASSERT_MSG(accessor->type == cgltf_type_vec3, "Vertex normals should be a vec3"); - - for (cgltf_size v = 0; v < accessor->count; ++v) { - Vec3 pos; - cgltf_accessor_read_float(accessor, v, &pos.x, 3); - Vec3_darray_push(normals, pos); - } -} - -void load_texcoord_components(Vec2_darray* texcoords, cgltf_accessor* accessor) { - TRACE("Load texture coordinates from accessor"); - CASSERT(accessor->component_type == cgltf_component_type_r_32f); - CASSERT_MSG(accessor->type == cgltf_type_vec2, "Texture coordinates should be a vec2"); - - for (cgltf_size v = 0; v < accessor->count; ++v) { - Vec2 tex; - bool success = cgltf_accessor_read_float(accessor, v, &tex.x, 2); - if (!success) { - ERROR("Error loading tex coord"); - } - Vec2_darray_push(texcoords, tex); - } -} - -void load_joint_index_components(Vec4i_darray* joint_indices, cgltf_accessor* accessor) { - TRACE("Load joint indices from accessor"); - CASSERT(accessor->component_type == cgltf_component_type_r_16u); - CASSERT_MSG(accessor->type == cgltf_type_vec4, "Joint indices should be a vec4"); - Vec4i tmp_joint_index; - Vec4 joints_as_floats; - for (cgltf_size v = 0; v < accessor->count; ++v) { - cgltf_accessor_read_float(accessor, v, &joints_as_floats.x, 4); - tmp_joint_index.x = (u32)joints_as_floats.x; - tmp_joint_index.y = (u32)joints_as_floats.y; - tmp_joint_index.z = (u32)joints_as_floats.z; - tmp_joint_index.w = (u32)joints_as_floats.w; - printf("Joints affecting vertex %d : %d %d %d %d\n", v, tmp_joint_index.x, tmp_joint_index.y, - tmp_joint_index.z, tmp_joint_index.w); - Vec4i_darray_push(joint_indices, tmp_joint_index); - } -} - -bool model_load_gltf_str(const char* file_string, const char* filepath, Str8 relative_path, - Model* out_model, bool invert_textures_y) { - TRACE("Load GLTF from string"); - - // Setup temps - Vec3_darray* tmp_positions = Vec3_darray_new(1000); - Vec3_darray* tmp_normals = Vec3_darray_new(1000); - Vec2_darray* tmp_uvs = Vec2_darray_new(1000); - Vec4i_darray* tmp_joint_indices = Vec4i_darray_new(1000); - Vec4_darray* tmp_weights = Vec4_darray_new(1000); - Material_darray* tmp_materials = Material_darray_new(1); - Mesh_darray* tmp_meshes = Mesh_darray_new(1); - i32_darray* tmp_material_indexes = i32_darray_new(1); - - Joint_darray* joints = Joint_darray_new(256); - - cgltf_options options = { 0 }; - cgltf_data* data = NULL; - cgltf_result result = cgltf_parse_file(&options, filepath, &data); - if (result != cgltf_result_success) { - WARN("gltf load failed"); - // TODO: cleanup arrays(allocate all from arena ?) - return false; - } - - cgltf_load_buffers(&options, data, filepath); - DEBUG("loaded buffers"); - - // --- Skin - size_t num_skins = data->skins_count; - bool is_skinned = false; - Armature main_skeleton = { 0 }; - if (num_skins == 1) { - is_skinned = true; - } else if (num_skins > 1) { - WARN("GLTF files with more than 1 skin are not supported"); - return false; - } - - if (is_skinned) { - cgltf_skin* gltf_skin = data->skins; - DEBUG("loading skin %s", gltf_skin->name); - size_t num_joints = gltf_skin->joints_count; - DEBUG("# Joints %d", num_joints); - - // Create our data that will be placed onto the model - Armature armature = { .label = "test_skin" }; - printf("Skin %s\n", gltf_skin->name); - // armature.label = Clone_cstr(&armature.arena, gltf_skin->name); - armature.joints = joints; // ! Make sure not to free this - - cgltf_accessor* gltf_inverse_bind_matrices = gltf_skin->inverse_bind_matrices; - - // --- Joints - // for each one we'll spit out a joint - for (size_t i = 0; i < num_joints; i++) { - // Get the joint and assign its node index for later referencing - cgltf_node* joint_node = gltf_skin->joints[i]; - TRACE("Joint %d (node index %d)", i, cgltf_node_index(data, joint_node)); - Joint joint_i = { .debug_label = "test_joint", - .node_idx = cgltf_node_index(data, joint_node), - .inverse_bind_matrix = mat4_ident() }; - - if (joint_node->children_count > 0 && !joint_node->has_translation && - !joint_node->has_rotation) { - WARN("Joint node with index %d is the root node", i); - joint_i.transform_components = TRANSFORM_DEFAULT; - joint_i.parent = -1; - for (u32 c_i = 0; c_i < joint_node->children_count; c_i++) { - joint_i.children[c_i] = cgltf_node_index(data, joint_node->children[c_i]); - joint_i.children_count++; - } - } else { - TRACE("Storing joint transform"); - joint_i.transform_components = TRANSFORM_DEFAULT; - if (joint_node->has_translation) { - memcpy(&joint_i.transform_components.position, &joint_node->translation, 3 * sizeof(f32)); - } - if (joint_node->has_rotation) { - memcpy(&joint_i.transform_components.rotation, &joint_node->rotation, 4 * sizeof(f32)); - } - if (joint_node->has_scale) { - memcpy(&joint_i.transform_components.scale, &joint_node->scale, 3 * sizeof(f32)); - } - joint_i.parent = cgltf_node_index(data, joint_node->parent); - } - // Calculate and store the starting transform of the joint - joint_i.local_transform = transform_to_mat(&joint_i.transform_components); - // Read in the inverse bind matrix - cgltf_accessor_read_float(gltf_inverse_bind_matrices, i, &joint_i.inverse_bind_matrix.data[0], - 16); - Joint_darray_push(armature.joints, joint_i); - } - main_skeleton = armature; - // out_model->armature = armature; - // out_model->has_joints = true; - } - - // --- Materials - size_t num_materials = GLTF_LoadMaterials(data, relative_path, tmp_materials); - - // --- Meshes - size_t num_meshes = data->meshes_count; - TRACE("Num meshes %d", num_meshes); - for (size_t m = 0; m < num_meshes; m++) { - printf("Primitive count %d\n", data->meshes[m].primitives_count); - for (size_t prim_i = 0; prim_i < data->meshes[m].primitives_count; prim_i++) { - DEBUG("Primitive %d\n", prim_i); - - cgltf_primitive primitive = data->meshes[m].primitives[prim_i]; - DEBUG("Found %d attributes", primitive.attributes_count); - - for (cgltf_size a = 0; a < primitive.attributes_count; a++) { - cgltf_attribute attribute = primitive.attributes[a]; - if (attribute.type == cgltf_attribute_type_position) { - cgltf_accessor* accessor = attribute.data; - load_position_components(tmp_positions, accessor); - } else if (attribute.type == cgltf_attribute_type_normal) { - cgltf_accessor* accessor = attribute.data; - load_normal_components(tmp_normals, accessor); - } else if (attribute.type == cgltf_attribute_type_texcoord) { - cgltf_accessor* accessor = attribute.data; - load_texcoord_components(tmp_uvs, accessor); - } else if (attribute.type == cgltf_attribute_type_joints) { - TRACE("Load joint indices from accessor"); - cgltf_accessor* accessor = attribute.data; - load_joint_index_components(tmp_joint_indices, accessor); - } else if (attribute.type == cgltf_attribute_type_weights) { - TRACE("Load joint weights from accessor"); - cgltf_accessor* accessor = attribute.data; - CASSERT(accessor->component_type == cgltf_component_type_r_32f); - CASSERT(accessor->type == cgltf_type_vec4); - - for (cgltf_size v = 0; v < accessor->count; ++v) { - Vec4 weights; - cgltf_accessor_read_float(accessor, v, &weights.x, 4); - printf("Weights affecting vertex %d : %f %f %f %f\n", v, weights.x, weights.y, - weights.z, weights.w); - Vec4_darray_push(tmp_weights, weights); - } - } else { - WARN("Unhandled cgltf_attribute_type: %s. skipping..", attribute.name); - } - } - // mesh.vertex_bone_data = vertex_bone_data_darray_new(1); - i32 mat_idx = -1; - if (primitive.material != NULL) { - DEBUG("Primitive Material %s", primitive.material->name); - // FIXME! - for (u32 i = 0; i < Material_darray_len(tmp_materials); i++) { - printf("%s vs %s \n", primitive.material->name, tmp_materials->data[i].name); - if (strcmp(primitive.material->name, tmp_materials->data[i].name) == 0) { - INFO("Found material"); - mat_idx = i; - i32_darray_push(tmp_material_indexes, mat_idx); - break; - } - } - } else { - i32_darray_push(tmp_material_indexes, -1); - } - - TRACE("Vertex data has been loaded"); - - Vertex_darray* geo_vertices = Vertex_darray_new(3); - u32_darray* geo_indices = u32_darray_new(0); - - // Store vertices - printf("Positions %d Normals %d UVs %d\n", tmp_positions->len, tmp_normals->len, - tmp_uvs->len); - // assert(tmp_positions->len == tmp_normals->len); - // assert(tmp_normals->len == tmp_uvs->len); - bool has_normals = tmp_normals->len > 0; - bool has_uvs = tmp_uvs->len > 0; - for (u32 v_i = 0; v_i < tmp_positions->len; v_i++) { - Vertex v = { 0 }; - if (is_skinned) { - v.skinned_3d.position = tmp_positions->data[v_i]; - v.skinned_3d.normal = has_normals ? tmp_normals->data[v_i] : VEC3_ZERO, - v.skinned_3d.tex_coords = has_uvs ? tmp_uvs->data[v_i] : vec2_create(0., 0.); - v.skinned_3d.bone_ids = tmp_joint_indices->data[v_i]; - v.skinned_3d.bone_weights = tmp_weights->data[v_i]; - } else { - v.static_3d.position = tmp_positions->data[v_i]; - v.static_3d.normal = has_normals ? tmp_normals->data[v_i] : VEC3_ZERO, - v.static_3d.tex_coords = has_uvs ? tmp_uvs->data[v_i] : vec2_create(0., 0.); - } - Vertex_darray_push(geo_vertices, v); - }; - - // Store indices - cgltf_accessor* indices = primitive.indices; - if (primitive.indices > 0) { - WARN("indices! %d", indices->count); - - // store indices - for (cgltf_size i = 0; i < indices->count; ++i) { - cgltf_uint ei; - cgltf_accessor_read_uint(indices, i, &ei, 1); - u32_darray_push(geo_indices, ei); - } - - Geometry* geometry = malloc(sizeof(Geometry)); - geometry->format = is_skinned ? VERTEX_SKINNED : VERTEX_STATIC_3D; - geometry->has_indices = true; - geometry->vertices = geo_vertices; - geometry->indices = geo_indices; - geometry->index_count = geo_indices->len; - - Mesh m = Mesh_Create(geometry, false); - if (is_skinned) { - m.is_skinned = true; - m.armature = main_skeleton; - } - Mesh_darray_push(tmp_meshes, m); - - Vec3_darray_clear(tmp_positions); - Vec3_darray_clear(tmp_normals); - Vec2_darray_clear(tmp_uvs); - Vec4i_darray_clear(tmp_joint_indices); - Vec4_darray_clear(tmp_weights); - } else { - WARN("No indices found. Ignoring mesh..."); - } - } - - // --- Animations - size_t num_animations = data->animations_count; - TRACE("Num animations %d", num_animations); - - if (num_animations > 0) { - if (!out_model->animations) { - out_model->animations = AnimationClip_darray_new(num_animations); - } - out_model->anim_arena = arena_create(malloc(MB(1)), MB(1)); - arena* arena = &out_model->anim_arena; - - // Iterate over each animation in the GLTF - for (int anim_idx = 0; anim_idx < data->animations_count; anim_idx++) { - cgltf_animation animation = data->animations[anim_idx]; - AnimationClip clip = { 0 }; - clip.clip_name = "test anim clip"; - clip.channels = AnimationSampler_darray_new(1); - - // for each animation, loop through all the channels - for (size_t c = 0; c < animation.channels_count; c++) { - cgltf_animation_channel channel = animation.channels[c]; - - AnimationSampler sampler = { 0 }; - - KeyframeKind data_type; - - switch (channel.target_path) { - case cgltf_animation_path_type_rotation: - data_type = KEYFRAME_ROTATION; - break; - case cgltf_animation_path_type_translation: - data_type = KEYFRAME_TRANSLATION; - break; - case cgltf_animation_path_type_scale: - data_type = KEYFRAME_SCALE; - break; - case cgltf_animation_path_type_weights: - data_type = KEYFRAME_WEIGHTS; - WARN("Morph target weights arent supported yet"); - return false; - default: - WARN("unsupported animation type"); - return false; - } - - sampler.current_index = 0; - sampler.animation.interpolation = INTERPOLATION_LINEAR; // NOTE: hardcoded for now - - // Keyframe times - size_t n_frames = channel.sampler->input->count; - CASSERT_MSG(channel.sampler->input->component_type == cgltf_component_type_r_32f, - "Expected animation sampler input component to be type f32"); - f32* times = arena_alloc(arena, n_frames * sizeof(f32)); - sampler.animation.n_timestamps = n_frames; - sampler.animation.timestamps = times; - cgltf_accessor_unpack_floats(channel.sampler->input, times, n_frames); - - // Keyframe values - size_t n_values = channel.sampler->output->count; - CASSERT_MSG(n_frames == n_values, "keyframe times = keyframe values"); - - Keyframes keyframes = { 0 }; - keyframes.kind = data_type; - keyframes.count = n_values; - keyframes.values = arena_alloc(arena, n_values * sizeof(Keyframe)); - for (cgltf_size v = 0; v < channel.sampler->output->count; ++v) { - switch (data_type) { - case KEYFRAME_ROTATION: { - Quat rot; - cgltf_accessor_read_float(channel.sampler->output, v, &rot.x, 4); - // printf("Quat %f %f %f %f\n", rot.x, rot.y, rot.z, rot.w); - keyframes.values[v].rotation = rot; - break; - } - case KEYFRAME_TRANSLATION: { - Vec3 trans; - cgltf_accessor_read_float(channel.sampler->output, v, &trans.x, 3); - keyframes.values[v].translation = trans; - break; - } - case KEYFRAME_SCALE: { - Vec3 scale; - cgltf_accessor_read_float(channel.sampler->output, v, &scale.x, 3); - keyframes.values[v].scale = scale; - break; - } - case KEYFRAME_WEIGHTS: { - // TODO: morph weights - break; - } - } - } - sampler.animation.values = keyframes; - sampler.min = channel.sampler->input->min[0]; - sampler.max = channel.sampler->input->max[0]; - - // *target_property = sampler; - printf("%d timestamps between %f and %f\n", sampler.animation.n_timestamps, sampler.min, - sampler.max); - - // TODO: get target - size_t target_index = cgltf_node_index(data, channel.target_node); - size_t joint_index = 0; - bool found = false; - for (u32 ji = 0; ji < main_skeleton.joints->len; ji++) { - if (main_skeleton.joints->data[ji].node_idx == target_index) { - joint_index = ji; - found = true; - break; - } - } - if (!found) { - WARN("Coulndnt find joint index"); - } - sampler.target_joint_idx = - joint_index; // NOTE: this assuming the target is a joint at the moment - AnimationSampler_darray_push(clip.channels, sampler); - } - - AnimationClip_darray_push(out_model->animations, clip); - } - } - - // exit(0); - } - - num_meshes = tmp_meshes->len; - - // we now have an array of meshes, materials, and the material which each mesh should get - out_model->meshes = malloc(num_meshes * sizeof(MeshHandle)); - out_model->mesh_count = num_meshes; - out_model->materials = malloc(num_materials * sizeof(MaterialHandle)); - out_model->material_count = num_materials; - - MaterialHandle* mat_handles = calloc(num_materials, sizeof(MaterialHandle)); - for (u32 mat_i = 0; mat_i < num_materials; mat_i++) { - mat_handles[mat_i] = - Material_pool_insert(Render_GetMaterialPool(), &tmp_materials->data[mat_i]); - } - memcpy(out_model->materials, mat_handles, num_materials * sizeof(MaterialHandle)); - - for (u32 mesh_i = 0; mesh_i < num_meshes; mesh_i++) { - i32 mat_idx = tmp_material_indexes->data[mesh_i]; - if (mat_idx > 0) { - tmp_meshes->data[mesh_i].material = mat_handles[mat_idx]; - - } else { - Material default_mat = PBRMaterialDefault(); - tmp_meshes->data[mesh_i].material = - Material_pool_insert(Render_GetMaterialPool(), &default_mat); - } - MeshHandle mesh = Mesh_pool_insert(Render_GetMeshPool(), &tmp_meshes->data[mesh_i]); - out_model->meshes[mesh_i] = mesh; - } - - free(mat_handles); - - return true; -} - -const char* bool_yes_no(bool pred) { return pred ? "Yes" : "No"; } - -// Loads all materials -size_t GLTF_LoadMaterials(cgltf_data* data, Str8 relative_path, Material_darray* out_materials) { - size_t num_materials = data->materials_count; - TRACE("Num materials %d", num_materials); - for (size_t m = 0; m < num_materials; m++) { - cgltf_material gltf_material = data->materials[m]; - TRACE("Loading material '%s'", gltf_material.name); - cgltf_pbr_metallic_roughness pbr = gltf_material.pbr_metallic_roughness; - - Material our_material = PBRMaterialDefault(); // focusing on PBR materials for now - - our_material.base_colour = - vec3(pbr.base_color_factor[0], pbr.base_color_factor[1], pbr.base_color_factor[2]); - our_material.metallic = pbr.metallic_factor; - our_material.roughness = pbr.roughness_factor; - - // -- albedo / base colour - cgltf_texture_view albedo_tex_view = pbr.base_color_texture; - bool has_albedo_texture = albedo_tex_view.texture != NULL; - TRACE("Has PBR base colour texture? %s", bool_yes_no(has_albedo_texture)); - printf("Base colour factor: %f %f %f\n", pbr.base_color_factor[0], pbr.base_color_factor[1], - pbr.base_color_factor[2]); - if (has_albedo_texture) { - char albedo_map_path[1024]; - snprintf(albedo_map_path, sizeof(albedo_map_path), "%s/%s", relative_path.buf, - albedo_tex_view.texture->image->uri); - our_material.albedo_map = TextureLoadFromFile(albedo_map_path); - } else { - our_material.albedo_map = Render_GetWhiteTexture(); - WARN("GLTF model has no albedo map"); - our_material.base_colour = - vec3_create(pbr.base_color_factor[0], pbr.base_color_factor[1], pbr.base_color_factor[2]); - } - - // -- metallic - cgltf_texture_view metal_rough_tex_view = pbr.metallic_roughness_texture; - printf("Metal factor: %f\n", pbr.metallic_factor); - printf("Roughness factor: %f\n", pbr.roughness_factor); - if (metal_rough_tex_view.texture != NULL) { - char metal_rough_map_path[1024]; - snprintf(metal_rough_map_path, sizeof(metal_rough_map_path), "%s/%s", relative_path.buf, - metal_rough_tex_view.texture->image->uri); - our_material.metallic_roughness_map = TextureLoadFromFile(metal_rough_map_path); - } else { - WARN("GLTF model has no metal/roughness map"); - our_material.metallic = pbr.metallic_factor; - our_material.roughness = pbr.roughness_factor; - } - - cgltf_texture_view normal_tex_view = gltf_material.normal_texture; - if (normal_tex_view.texture != NULL) { - char normal_map_path[1024]; - snprintf(normal_map_path, sizeof(normal_map_path), "%s/%s", relative_path.buf, - normal_tex_view.texture->image->uri); - our_material.normal_map = TextureLoadFromFile(normal_map_path); - } else { - WARN("GLTF model has no normal map"); - } - - u32 string_length = strlen(gltf_material.name) + 1; - assert(string_length < 64); - strcpy(our_material.name, gltf_material.name); - - Material_darray_push(out_materials, our_material); - } - - return out_materials->len; -} |