diff options
author | Omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-04-07 13:50:40 +1000 |
---|---|---|
committer | Omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-04-07 13:50:40 +1000 |
commit | 42924fe7b32e93bf55ce034467ceb52e0436c303 (patch) | |
tree | fbdf14de2bab718cadb6492d3774d33a0f50ff2f | |
parent | d9f9479694d8a4d74822a876516282329db5ea3d (diff) |
visualising bone indices
-rw-r--r-- | assets/shaders/blinn_phong.frag | 4 | ||||
-rw-r--r-- | assets/shaders/skinned.vert | 46 | ||||
-rw-r--r-- | examples/skinned_animation/ex_skinned_animation.c | 25 | ||||
-rw-r--r-- | src/animation.h | 8 | ||||
-rw-r--r-- | src/maths/maths_types.h | 6 | ||||
-rw-r--r-- | src/renderer/render.c | 62 | ||||
-rw-r--r-- | src/renderer/render_types.h | 2 | ||||
-rw-r--r-- | src/resources/gltf.c | 83 |
8 files changed, 158 insertions, 78 deletions
diff --git a/assets/shaders/blinn_phong.frag b/assets/shaders/blinn_phong.frag index 095b19a..adcc53e 100644 --- a/assets/shaders/blinn_phong.frag +++ b/assets/shaders/blinn_phong.frag @@ -33,6 +33,7 @@ in VS_OUT { vec3 Normal; vec2 TexCoords; vec4 FragPosLightSpace; + vec4 Color; } fs_in; // --- Uniforms @@ -55,7 +56,8 @@ void main() { result += CalcPointLight(pointLights[i], norm, fs_in.FragPos, viewDir); } - FragColor = vec4(result, 1.0); + // FragColor = vec4(result, 1.0); + FragColor = fs_in.Color + 0.5; } vec3 CalcDirLight(DirLight light, vec3 normal, vec3 viewDir) diff --git a/assets/shaders/skinned.vert b/assets/shaders/skinned.vert index 3d0c2cd..cb2ca85 100644 --- a/assets/shaders/skinned.vert +++ b/assets/shaders/skinned.vert @@ -13,7 +13,7 @@ uniform mat4 lightSpaceMatrix; const int MAX_BONES = 100; const int MAX_BONE_INFLUENCES = 4; -uniform mat4 finalBoneMatrices[MAX_BONES]; +uniform mat4 boneMatrices[MAX_BONES]; // TODO! // Output out VS_OUT { @@ -21,27 +21,39 @@ out VS_OUT { vec3 Normal; vec2 TexCoords; vec4 FragPosLightSpace; + vec4 Color; } vs_out; void main() { - vec4 totalPosition = vec4(0.0f); - for(int i = 0 ; i < MAX_BONE_INFLUENCES ; i++) { - if(inBoneIndices[i] == -1) - continue; - if(inBoneIndices[i] >=MAX_BONES) - { - totalPosition = vec4(inPos,1.0f); - break; - } - vec4 localPosition = finalBoneMatrices[inBoneIndices[i]] * vec4(inPos,1.0f); - totalPosition += localPosition * inWeights[i]; - vec3 localNormal = mat3(finalBoneMatrices[inBoneIndices[i]]) * inNormal; - vs_out.Normal = localNormal; - } - - vs_out.FragPos = vec3(model * vec4(inPos, 1.0)); + // vec4 totalPosition = vec4(0.0f); + // for(int i = 0 ; i < MAX_BONE_INFLUENCES ; i++) { + // if(inBoneIndices[i] == 0) + // continue; + // if(inBoneIndices[i] >=MAX_BONES) + // { + // totalPosition = vec4(inPos,1.0f); + // break; + // } + // vec4 localPosition = finalBoneMatrices[inBoneIndices[i]] * vec4(inPos,1.0f); + // totalPosition += localPosition * inWeights[i]; + // vec3 localNormal = mat3(finalBoneMatrices[inBoneIndices[i]]) * inNormal; + // vs_out.Normal = localNormal; + // } + + + mat4 skinMatrix = // mat4(1.0) + // boneMatrices[int(inBoneIndices.z)]; // should just be the identtiy + inWeights.x * boneMatrices[int(inBoneIndices.x)] + + inWeights.y * boneMatrices[int(inBoneIndices.y)] + + inWeights.z * boneMatrices[int(inBoneIndices.z)] + + inWeights.w * boneMatrices[int(inBoneIndices.w)]; + + vec4 totalPosition = skinMatrix * vec4(inPos, 1.0); + + vs_out.FragPos = vec3(model * totalPosition); // vs_out.Normal = inNormal; vs_out.TexCoords = inTexCoords; vs_out.FragPosLightSpace = lightSpaceMatrix * vec4(vs_out.FragPos, 1.0); + vs_out.Color = inWeights; gl_Position = projection * view * model * totalPosition; }
\ No newline at end of file diff --git a/examples/skinned_animation/ex_skinned_animation.c b/examples/skinned_animation/ex_skinned_animation.c index 3138256..43eb715 100644 --- a/examples/skinned_animation/ex_skinned_animation.c +++ b/examples/skinned_animation/ex_skinned_animation.c @@ -1,3 +1,4 @@ +#include <assert.h> #include <glfw3.h> #include "../example_scene.h" @@ -30,10 +31,22 @@ int main() { core* core = core_bringup(); - model_handle animated_cube_handle = + model_handle handle = model_load_gltf(core, "assets/models/gltf/SimpleSkin/glTF/SimpleSkin.gltf", false); - model* cube = &core->models->data[animated_cube_handle.raw]; - model_upload_meshes(&core->renderer, cube); + + model* simple_skin = &core->models->data[handle.raw]; + + // Okay, right here we've loaded the model. let's assert some facts + assert(simple_skin->animations->len == 1); + assert(simple_skin->animations->data[0].rotation != NULL); + assert(simple_skin->animations->data[0].translation == NULL); + assert(simple_skin->animations->data[0].scale == NULL); + + mesh* m = &simple_skin->meshes->data[0]; + assert(m->is_skinned); + assert(m->bones->len == 2); // 1 root and 1 extra joint + + model_upload_meshes(&core->renderer, simple_skin); scene our_scene = make_default_scene(); @@ -48,7 +61,7 @@ int main() { // Main loop const f32 camera_lateral_speed = 0.2; - const f32 camera_zoom_speed = 0.15; + const f32 camera_zoom_speed = 0.10; // animation // animation_clip track = cube->animations->data[0]; @@ -86,7 +99,7 @@ int main() { quat rot = quat_ident(); transform tf = transform_create(VEC3_ZERO, rot, 1.0); - draw_skinned_model(&core->renderer, &game.camera, cube, tf, &our_scene); + draw_skinned_model(&core->renderer, &game.camera, simple_skin, tf, &our_scene); // gfx_backend_draw_frame(&core->renderer, &game.camera, model, NULL); @@ -94,7 +107,7 @@ int main() { } INFO("Shutting down"); - model_destroy(cube); + model_destroy(simple_skin); core_shutdown(core); diff --git a/src/animation.h b/src/animation.h index 18d3ba9..9d5d03b 100644 --- a/src/animation.h +++ b/src/animation.h @@ -31,6 +31,7 @@ typedef struct keyframes { typedef struct joint { char* name; // optional transform transform_components; + mat4 inverse_bind_matrix; mat4 local_transform; } joint; @@ -61,4 +62,11 @@ typedef struct animation_clip { animation_sampler* weights; } animation_clip; +typedef struct skinned_animation { + mat4* joint_matrices; + size_t n_joints; +} skinned_animation; + +// void animation_update_joint_matrices(animation_clip* ) + void animation_play(animation_clip* clip);
\ No newline at end of file diff --git a/src/maths/maths_types.h b/src/maths/maths_types.h index 6d38fc7..53cac55 100644 --- a/src/maths/maths_types.h +++ b/src/maths/maths_types.h @@ -64,4 +64,8 @@ typedef struct transform { typedef struct vec4i { i32 x, y, z, w; -} vec4i;
\ No newline at end of file +} vec4i; + +typedef struct vec4u { + u32 x, y, z, w; +} vec4u;
\ No newline at end of file diff --git a/src/renderer/render.c b/src/renderer/render.c index e420043..42f6ee4 100644 --- a/src/renderer/render.c +++ b/src/renderer/render.c @@ -97,6 +97,7 @@ void default_material_init() { } void model_destroy(model* model) { + TRACE("Freeing all data for model %s", model->name); arena_free_all(&model->animation_data_arena); arena_free_storage(&model->animation_data_arena); mesh_darray_free(model->meshes); @@ -175,19 +176,31 @@ void draw_skinned_mesh(renderer* ren, mesh* mesh, transform tf, material* mat, m // bind textures bind_texture(lighting_shader, &mat->diffuse_texture, 0); // bind to slot 0 bind_texture(lighting_shader, &mat->specular_texture, 1); // bind to slot 1 - uniform_f32(lighting_shader.program_id, "material.shininess", 32.); - // upload model transform + // Uniforms + uniform_f32(lighting_shader.program_id, "material.shininess", 32.); mat4 trans = mat4_translation(tf.position); mat4 rot = mat4_rotation(tf.rotation); mat4 scale = mat4_scale(tf.scale); mat4 model_tf = mat4_mult(trans, mat4_mult(rot, scale)); - uniform_mat4f(lighting_shader.program_id, "model", &model_tf); - // upload view & projection matrices uniform_mat4f(lighting_shader.program_id, "view", view); uniform_mat4f(lighting_shader.program_id, "projection", proj); + // bone transforms + size_t n_bones = mesh->bones->len; + + // for now assume correct ordering + mat4* bone_transforms = malloc(n_bones * sizeof(mat4)); + for (int bone_i = 0; bone_i < n_bones; bone_i++) { + bone_transforms[bone_i] = mat4_ident(); + } + + glUniformMatrix4fv(glGetUniformLocation(lighting_shader.program_id, "boneMatrices"), n_bones, + GL_FALSE, &bone_transforms->data[0]); + + free(bone_transforms); + // draw triangles u32 num_vertices = vertex_darray_len(mesh->vertices); draw_primitives(CEL_PRIMITIVE_TOPOLOGY_TRIANGLE, 0, num_vertices); @@ -201,11 +214,11 @@ void draw_skinned_model(renderer* ren, camera* cam, model* model, transform tf, set_shader(ren->skinned); // set camera uniform - uniform_vec3f(ren->blinn_phong.program_id, "viewPos", &cam->position); + uniform_vec3f(ren->skinned.program_id, "viewPos", &cam->position); // set light uniforms - dir_light_upload_uniforms(ren->blinn_phong, &scene->dir_light); + dir_light_upload_uniforms(ren->skinned, &scene->dir_light); for (int i = 0; i < scene->n_point_lights; i++) { - point_light_upload_uniforms(ren->blinn_phong, &scene->point_lights[i], '0' + i); + point_light_upload_uniforms(ren->skinned, &scene->point_lights[i], '0' + i); } for (size_t i = 0; i < mesh_darray_len(model->meshes); i++) { @@ -213,7 +226,8 @@ void draw_skinned_model(renderer* ren, camera* cam, model* model, transform tf, if (vertex_darray_len(m->vertices) == 0) { continue; } - material* mat = &model->materials->data[m->material_index]; + // material* mat = &model->materials->data[m->material_index]; + material* mat = &DEFAULT_MATERIAL; draw_skinned_mesh(ren, m, tf, mat, &view, &proj); } } @@ -272,21 +286,28 @@ void model_upload_meshes(renderer* ren, model* model) { // + j].uv.y; // } // } - size_t vertex_size = mesh.is_skinned - ? sizeof(vec3) * 2 + sizeof(vec2) + sizeof(u32) * 4 + sizeof(vec4) - : sizeof(vec3) * 2 + sizeof(vec2); - if (!mesh.is_skinned) { - printf("sizeof(vertex) -> %ld, vertex_size -> %ld\n", sizeof(vertex), vertex_size); + size_t static_vertex_size = 2 * sizeof(vec3) + sizeof(vec2); + size_t skinned_vertex_size = 2 * sizeof(vec3) + sizeof(vec2) + 4 * sizeof(u32) + sizeof(vec4); + size_t vertex_size = mesh.is_skinned ? skinned_vertex_size : static_vertex_size; + + TRACE("sizeof(vertex) -> %ld, vertex_size -> %ld\n", sizeof(vertex), vertex_size); + if (mesh.is_skinned) { + assert(vertex_size == (12 + 12 + 8 + 16 + 16)); + } else { assert(vertex_size == sizeof(vertex)); + assert(vertex_size == 8 * sizeof(float)); } size_t buffer_size = vertex_size * num_vertices; u8* bytes = malloc(buffer_size); for (int i = 0; i < num_vertices; i++) { u8* p = bytes + vertex_size * i; - u8* bone_data_offset = p + sizeof(u32) * 4 + sizeof(vec4); + u8* bone_data_offset = p + static_vertex_size; memcpy(p, &mesh.vertices->data[i], sizeof(vertex)); - memcpy(bone_data_offset, &mesh.vertex_bone_data->data[i], sizeof(vertex_bone_data)); + if (mesh.is_skinned) { + // printf("") + memcpy(bone_data_offset, &mesh.vertex_bone_data->data[i], sizeof(vertex_bone_data)); + } } // 4. upload data @@ -295,17 +316,22 @@ void model_upload_meshes(renderer* ren, model* model) { // 5. cont. set mesh vertex layout glBindVertexArray(model->meshes->data[mesh_i].vao); // position attribute - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)0); glEnableVertexAttribArray(0); // normal vector attribute - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float))); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertex_size, (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); // tex coords - glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float))); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, vertex_size, (void*)(6 * sizeof(float))); glEnableVertexAttribArray(2); // skinning (optional) if (mesh.is_skinned) { + glEnableVertexAttribArray(3); + glVertexAttribIPointer(3, 4, GL_INT, vertex_size, (void*)(8 * sizeof(float))); + + glEnableVertexAttribArray(4); + glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, vertex_size, (void*)(12 * sizeof(float))); } } diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h index 61571e1..bfed18d 100644 --- a/src/renderer/render_types.h +++ b/src/renderer/render_types.h @@ -120,7 +120,7 @@ typedef struct vertex { } vertex; typedef struct vertex_bone_data { - vec4i joints; /** @brief 4 indices of joints that influence vectors position */ + vec4u joints; /** @brief 4 indices of joints that influence vectors position */ vec4 weights; /** @brief weight (0,1) of each joint */ } vertex_bone_data; diff --git a/src/resources/gltf.c b/src/resources/gltf.c index c7c1f55..7efd2bb 100644 --- a/src/resources/gltf.c +++ b/src/resources/gltf.c @@ -28,7 +28,7 @@ typedef struct face face; KITC_DECL_TYPED_ARRAY(vec3) KITC_DECL_TYPED_ARRAY(vec2) KITC_DECL_TYPED_ARRAY(u32) -KITC_DECL_TYPED_ARRAY(vec4i) +KITC_DECL_TYPED_ARRAY(vec4u) KITC_DECL_TYPED_ARRAY(vec4) KITC_DECL_TYPED_ARRAY(face) // KITC_DECL_TYPED_ARRAY(joint) @@ -86,9 +86,10 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel 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); + vec4u_darray *tmp_joint_indices = vec4u_darray_new(1000); vec4_darray *tmp_weights = vec4_darray_new(1000); joint_darray *tmp_joints = joint_darray_new(256); + vertex_bone_data_darray* tmp_vertex_bone_data = vertex_bone_data_darray_new(1000); cgltf_options options = { 0 }; cgltf_data *data = NULL; @@ -118,6 +119,8 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel size_t num_joints = gltf_skin->joints_count; DEBUG("# Joints %d", num_joints); + cgltf_accessor *gltf_inverse_bind_matrices = gltf_skin->inverse_bind_matrices; + // for each one we'll spit out a joint for (size_t i = 0; i < num_joints; i++) { cgltf_node *joint_node = gltf_skin->joints[i]; @@ -139,6 +142,8 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel // TODO: support scaling as vec instead of float } joint_i.local_transform = transform_to_mat(&joint_i.transform_components); + cgltf_accessor_read_float(gltf_inverse_bind_matrices, i, &joint_i.inverse_bind_matrix.data[0], + 16); joint_darray_push(tmp_joints, joint_i); } } @@ -238,7 +243,7 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel cgltf_accessor *accessor = attribute.data; assert(accessor->component_type == cgltf_component_type_r_16u); assert(accessor->type == cgltf_type_vec4); - vec4i joint_indices; + vec4u joint_indices; vec4 joints_as_floats; for (cgltf_size v = 0; v < accessor->count; ++v) { cgltf_accessor_read_float(accessor, v, &joints_as_floats.x, 4); @@ -246,9 +251,9 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel joint_indices.y = (u32)joints_as_floats.y; joint_indices.z = (u32)joints_as_floats.z; joint_indices.w = (u32)joints_as_floats.w; - // printf("Joints affecting %d %d %d %d\n", joint_indices.x, joint_indices.y, - // joint_indices.z, joint_indices.w); - vec4i_darray_push(tmp_joint_indices, joint_indices); + printf("Joints affecting vertex %d : %d %d %d %d\n", v, joint_indices.x, joint_indices.y, + joint_indices.z, joint_indices.w); + vec4u_darray_push(tmp_joint_indices, joint_indices); } } else if (attribute.type == cgltf_attribute_type_weights) { @@ -260,7 +265,8 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel for (cgltf_size v = 0; v < accessor->count; ++v) { vec4 weights; cgltf_accessor_read_float(accessor, v, &weights.x, 4); - // printf("Weights affecting %f %f %f %f\n", weights.x, weights.y, weights.z, weights.w); + 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 { @@ -270,9 +276,38 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel mesh mesh = { 0 }; mesh.vertices = vertex_darray_new(10); + mesh.vertex_bone_data =vertex_bone_data_darray_new(1); + + if (primitive.material != NULL) { + for (int i = 0; i < material_darray_len(out_model->materials); i++) { + printf("%s vs %s \n", primitive.material->name, out_model->materials->data[i].name); + if (strcmp(primitive.material->name, out_model->materials->data[i].name) == 0) { + TRACE("Found material"); + mesh.material_index = i; + break; + } + } + } + + if (is_skinned) { + mesh.is_skinned = true; + // mesh.vertex_bone_data = vertex_bone_data_darray_new(tmp_joint_indices->len); + mesh.bones = joint_darray_new(tmp_joints->len); + for (int i = 0; i < tmp_joint_indices->len; i++) { + vertex_bone_data data; + data.joints = tmp_joint_indices->data[i]; + data.weights = tmp_weights->data[i]; + vertex_bone_data_darray_push(tmp_vertex_bone_data, data); // Push the temp data that aligns with raw vertices + } + for (int i = 0; i < tmp_joints->len; i++) { + joint data = tmp_joints->data[i]; + joint_darray_push(mesh.bones, data); + } + } cgltf_accessor *indices = primitive.indices; if (primitive.indices > 0) { + WARN("indices!"); mesh.has_indices = true; mesh.indices = malloc(indices->count * sizeof(u32)); @@ -293,45 +328,25 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel vert.normal = tmp_normals->data[index]; vert.uv = tmp_uvs->data[index]; vertex_darray_push(mesh.vertices, vert); + + if (is_skinned) { + vertex_bone_data vbd = tmp_vertex_bone_data->data[index]; // create a copy + vertex_bone_data_darray_push(mesh.vertex_bone_data, vbd); + } + // for each vertex do the bone data } } else { mesh.has_indices = false; return false; // TODO } - if (primitive.material != NULL) { - for (int i = 0; i < material_darray_len(out_model->materials); i++) { - printf("%s vs %s \n", primitive.material->name, out_model->materials->data[i].name); - if (strcmp(primitive.material->name, out_model->materials->data[i].name) == 0) { - TRACE("Found material"); - mesh.material_index = i; - break; - } - } - } - - if (is_skinned) { - mesh.vertex_bone_data = vertex_bone_data_darray_new(tmp_joint_indices->len); - mesh.bones = joint_darray_new(tmp_joints->len); - for (int i = 0; i < tmp_joint_indices->len; i++) { - vertex_bone_data data; - data.joints = tmp_joint_indices->data[i]; - data.weights =tmp_weights->data[i]; - vertex_bone_data_darray_push(mesh.vertex_bone_data, data); - } - for (int i = 0; i < tmp_joints->len; i++) { - joint data = tmp_joints->data[i]; - joint_darray_push(mesh.bones, data); - } - } - mesh_darray_push(out_model->meshes, mesh); // clear data for each mesh vec3_darray_clear(tmp_positions); vec3_darray_clear(tmp_normals); vec2_darray_free(tmp_uvs); - vec4i_darray_clear(tmp_joint_indices); + vec4u_darray_clear(tmp_joint_indices); vec4_darray_clear(tmp_weights); joint_darray_clear(tmp_joints); } |