summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmniscient <17525998+omnisci3nce@users.noreply.github.com>2024-04-07 13:50:40 +1000
committerOmniscient <17525998+omnisci3nce@users.noreply.github.com>2024-04-07 13:50:40 +1000
commit42924fe7b32e93bf55ce034467ceb52e0436c303 (patch)
treefbdf14de2bab718cadb6492d3774d33a0f50ff2f
parentd9f9479694d8a4d74822a876516282329db5ea3d (diff)
visualising bone indices
-rw-r--r--assets/shaders/blinn_phong.frag4
-rw-r--r--assets/shaders/skinned.vert46
-rw-r--r--examples/skinned_animation/ex_skinned_animation.c25
-rw-r--r--src/animation.h8
-rw-r--r--src/maths/maths_types.h6
-rw-r--r--src/renderer/render.c62
-rw-r--r--src/renderer/render_types.h2
-rw-r--r--src/resources/gltf.c83
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);
}