summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoromnisci3nce <17525998+omnisci3nce@users.noreply.github.com>2024-04-04 22:53:13 +1100
committeromnisci3nce <17525998+omnisci3nce@users.noreply.github.com>2024-04-04 22:53:13 +1100
commit9baff5661f2ba8b57e1b0794e490e239b7ef80ca (patch)
tree11ae178c14f59c4fcb380cdcc1bf38d065c9eee2
parentaf97c4330a27a92d2362e30b70990e3aa5c9954a (diff)
loading animation data - step 1
-rw-r--r--examples/property_animation/ex_property_animation.c4
-rw-r--r--src/animation.c0
-rw-r--r--src/animation.h53
-rw-r--r--src/maths/primitives.h82
-rw-r--r--src/renderer/backends/backend_opengl.c4
-rw-r--r--src/renderer/render.c16
-rw-r--r--src/renderer/render.h2
-rw-r--r--src/renderer/render_types.h12
-rw-r--r--src/resources/gltf.c59
9 files changed, 194 insertions, 38 deletions
diff --git a/examples/property_animation/ex_property_animation.c b/examples/property_animation/ex_property_animation.c
index 38bafd5..e175b31 100644
--- a/examples/property_animation/ex_property_animation.c
+++ b/examples/property_animation/ex_property_animation.c
@@ -4,6 +4,7 @@
#include "core.h"
#include "input.h"
#include "keys.h"
+#include "log.h"
#include "maths.h"
#include "maths_types.h"
#include "primitives.h"
@@ -97,6 +98,9 @@ int main() {
render_frame_end(&core->renderer);
}
+ INFO("Shutting down");
+ model_destroy(cube);
+
core_shutdown(core);
return 0;
diff --git a/src/animation.c b/src/animation.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/animation.c
diff --git a/src/animation.h b/src/animation.h
new file mode 100644
index 0000000..b7c8ca4
--- /dev/null
+++ b/src/animation.h
@@ -0,0 +1,53 @@
+#pragma once
+
+#include "darray.h"
+#include "defines.h"
+#include "maths_types.h"
+
+KITC_DECL_TYPED_ARRAY(f32)
+
+typedef enum interpolation { INTERPOLATION_LINEAR, INTERPOLATION_COUNT } interpolation;
+
+typedef enum keyframe_kind {
+ KEYFRAME_ROTATION,
+ KEYFRAME_TRANSLATION,
+ KEYFRAME_SCALE,
+ KEYFRAME_WEIGHTS,
+} keyframe_kind;
+
+typedef union keyframe {
+ quat rotation;
+ vec3 translation;
+ vec3 scale;
+ float* weights;
+} keyframe;
+
+typedef struct keyframes {
+ keyframe_kind kind;
+ keyframe* values;
+ size_t count;
+} keyframes;
+
+typedef struct animation_spline {
+ f32_darray timestamps;
+ keyframes values;
+ interpolation interpolation;
+} animation_spline;
+
+typedef struct animation_sampler {
+ int current_index;
+ animation_spline animation;
+} animation_sampler;
+
+/** @brief Sample an animation at a given time `t` */
+keyframe animation_sample(animation_sampler sampler, f32 t);
+
+typedef struct animation_clip {
+ // A clip contains one or more animation curves
+ // for now I think we can just enumerate all of the properties (assuming *only* one per type is in
+ // a clip) NULL = this property is not animated in this clip
+ animation_sampler* rotation;
+ animation_sampler* translation;
+ animation_sampler* scale;
+ animation_sampler* weights;
+} animation_clip; \ No newline at end of file
diff --git a/src/maths/primitives.h b/src/maths/primitives.h
index b7fefa0..ed52c8c 100644
--- a/src/maths/primitives.h
+++ b/src/maths/primitives.h
@@ -34,38 +34,48 @@ static mesh prim_cube_mesh_create() {
(vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1, 0 } });
vertex_darray_push(
cube.vertices,
- (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1,1 } });
+ (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_NEG_Z, .uv = (vec2){ 1, 1 } });
vertex_darray_push(
cube.vertices,
(vertex){ .position = BACK_BOT_LEFT, .normal = VEC3_NEG_Z, .uv = (vec2){ 0, 1 } });
// front faces
- vertex_darray_push(cube.vertices,
- (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 1} });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 0 } });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 0} });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 1 } });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 1 } });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 0 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 1 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 0 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 0 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = FRONT_BOT_LEFT, .normal = VEC3_Z, .uv = (vec2){ 0, 1 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 1 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Z, .uv = (vec2){ 1, 0 } });
// top faces
vertex_darray_push(cube.vertices,
(vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_Y, .uv = (vec2){ 0, 0 } });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_Y, .uv = (vec2){ 0, 1 } });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 1 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = FRONT_TOP_LEFT, .normal = VEC3_Y, .uv = (vec2){ 0, 1 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 1 } });
vertex_darray_push(cube.vertices,
(vertex){ .position = BACK_TOP_LEFT, .normal = VEC3_Y, .uv = (vec2){ 0, 0 } });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 1 } });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 0 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 1 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_Y, .uv = (vec2){ 1, 0 } });
// bottom faces
vertex_darray_push(
@@ -88,18 +98,24 @@ static mesh prim_cube_mesh_create() {
(vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_NEG_Y, .uv = (vec2){ 0 } });
// right faces
- vertex_darray_push(cube.vertices,
- (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 0 } });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 1 } });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 0 } });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1,1 } });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 0 } });
- vertex_darray_push(cube.vertices,
- (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 1 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 0 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 1 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = BACK_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 0 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = BACK_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 1, 1 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = FRONT_TOP_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 0 } });
+ vertex_darray_push(
+ cube.vertices,
+ (vertex){ .position = FRONT_BOT_RIGHT, .normal = VEC3_X, .uv = (vec2){ 0, 1 } });
// left faces
vertex_darray_push(
diff --git a/src/renderer/backends/backend_opengl.c b/src/renderer/backends/backend_opengl.c
index 8df0933..b769002 100644
--- a/src/renderer/backends/backend_opengl.c
+++ b/src/renderer/backends/backend_opengl.c
@@ -42,9 +42,7 @@ bool gfx_backend_init(renderer *ren) {
return true;
}
-void gfx_backend_draw_frame(renderer* ren, camera* cam, mat4 model, texture* tex) {
-
-}
+void gfx_backend_draw_frame(renderer *ren, camera *cam, mat4 model, texture *tex) {}
void gfx_backend_shutdown(renderer *ren) {}
diff --git a/src/renderer/render.c b/src/renderer/render.c
index 2993225..2f5e553 100644
--- a/src/renderer/render.c
+++ b/src/renderer/render.c
@@ -1,3 +1,4 @@
+#include "mem.h"
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
@@ -88,6 +89,21 @@ void default_material_init() {
texture_data_upload(&DEFAULT_MATERIAL.specular_texture);
}
+void model_destroy(model* model) {
+ arena_free_all(&model->animation_data_arena);
+ arena_free_storage(&model->animation_data_arena);
+ mesh_darray_free(model->meshes);
+ material_darray_free(model->materials);
+ if (model->is_uploaded) {
+ // Delete gpu buffer data
+ for (u32 i = 0; i < mesh_darray_len(model->meshes); i++) {
+ // FIXME: dont leak Opengl
+ glDeleteBuffers(1, &model->meshes->data[i].vbo);
+ glDeleteVertexArrays(1, &model->meshes->data[i].vao);
+ }
+ }
+}
+
void draw_model(renderer* ren, camera* camera, model* model, transform tf, scene* scene) {
// TRACE("Drawing model: %s", model->name);
mat4 view;
diff --git a/src/renderer/render.h b/src/renderer/render.h
index b6dad00..f0118b6 100644
--- a/src/renderer/render.h
+++ b/src/renderer/render.h
@@ -35,5 +35,7 @@ void model_upload_meshes(renderer* ren, model* model);
void draw_model(renderer* ren, camera* camera, model* model, transform tf, scene* scene);
void draw_mesh(renderer* ren, mesh* mesh, transform tf, material* mat, mat4* view, mat4* proj);
+void model_destroy(model* model);
+
// ---
texture texture_data_load(const char* path, bool invert_y); // #frontend
diff --git a/src/renderer/render_types.h b/src/renderer/render_types.h
index 80e1372..8d12183 100644
--- a/src/renderer/render_types.h
+++ b/src/renderer/render_types.h
@@ -7,6 +7,7 @@
*/
#pragma once
+#include "animation.h"
#include "darray.h"
#include "maths.h"
#include "maths_types.h"
@@ -52,8 +53,8 @@ typedef struct renderer {
typedef struct texture {
u32 texture_id;
char name[MAX_TEXTURE_NAME_LEN];
- void* image_data;
- void* backend_data;
+ void *image_data;
+ void *backend_data;
u32 width;
u32 height;
u8 channel_count;
@@ -84,6 +85,11 @@ KITC_DECL_TYPED_ARRAY(material) // creates "material_darray"
#define TYPED_MATERIAL_ARRAY
#endif
+#ifndef TYPED_ANIMATION_CLIP_ARRAY
+KITC_DECL_TYPED_ARRAY(animation_clip) // creates "material_darray"
+#define TYPED_ANIMATION_CLIP_ARRAY
+#endif
+
// lights
typedef struct point_light {
vec3 position;
@@ -137,6 +143,8 @@ typedef struct model {
mesh_darray *meshes;
aabb_3d bbox;
material_darray *materials;
+ animation_clip_darray *animations;
+ arena animation_data_arena;
bool is_loaded;
bool is_uploaded;
} model;
diff --git a/src/resources/gltf.c b/src/resources/gltf.c
index 261c96f..b6e100f 100644
--- a/src/resources/gltf.c
+++ b/src/resources/gltf.c
@@ -1,11 +1,13 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include "animation.h"
#include "core.h"
#include "defines.h"
#include "file.h"
#include "loaders.h"
#include "log.h"
+#include "mem.h"
#include "path.h"
#include "render.h"
#include "render_types.h"
@@ -228,6 +230,63 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, str8 rel
printf("Mesh %d Mat index %d Mat name %s\n", i, mat_idx,
out_model->materials->data[mat_idx].name);
}
+
+ // Animations
+ TRACE("Num animations %d", data->animations_count);
+ size_t num_animations = data->animations_count;
+ if (num_animations > 0) {
+// Create an arena for all animation related data
+#define ANIMATION_STORAGE_ARENA_SIZE (1024 * 1024)
+ char *animation_backing_storage = malloc(ANIMATION_STORAGE_ARENA_SIZE);
+ // We'll store data on this arena so we can easily free it all at once later
+ arena anim_arena = arena_create(animation_backing_storage, ANIMATION_STORAGE_ARENA_SIZE);
+
+ if (!out_model->animations) {
+ out_model->animations = animation_clip_darray_new(num_animations);
+ }
+
+ for (int anim_idx = 0; anim_idx < data->animations_count; anim_idx++) {
+ cgltf_animation animation = data->animations[anim_idx];
+ animation_clip clip = { 0 };
+
+ for (size_t c = 0; c < animation.channels_count; c++) {
+ cgltf_animation_channel channel = animation.channels[c];
+
+ animation_sampler *sampler = arena_alloc(&anim_arena, sizeof(animation_sampler));
+
+ animation_sampler **target_property;
+ keyframe_kind data_type;
+
+ switch (channel.target_path) {
+ case cgltf_animation_path_type_rotation:
+ target_property = &clip.rotation;
+ data_type = KEYFRAME_ROTATION;
+ break;
+ default:
+ WARN("unsupported animation type");
+ return false;
+ }
+ *target_property = sampler;
+
+ sampler->current_index = 0;
+ sampler->animation.interpolation = INTERPOLATION_LINEAR;
+
+ // keyframe times
+ size_t n_frames = channel.sampler->input->count;
+ assert(channel.sampler->input->component_type == cgltf_component_type_r_32f);
+ // FIXME: CASSERT_MSG function "Expected animation sampler input component to be type f32 (keyframe times)");
+
+ sampler,
+
+ // keyframe values
+ size_t n_values = channel.sampler->output->count;
+ assert(n_frames == n_values);
+
+ sampler->animation.timestamps
+ }
+ }
+ }
+
return true;
}