diff options
author | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-08-13 20:29:27 +1000 |
---|---|---|
committer | omniscient <17525998+omnisci3nce@users.noreply.github.com> | 2024-08-13 20:29:27 +1000 |
commit | 567d384b698151e287e31140709c93f1b92e6db4 (patch) | |
tree | e00975124d3f002a8aaa22e85475d913c6950346 | |
parent | 13949ca02bcf9fcdfcc48ea7949f617553a260b6 (diff) |
loading joints and animations
37 files changed, 653 insertions, 587 deletions
diff --git a/.clang-format b/.clang-format index 441b1d8..059381e 100644 --- a/.clang-format +++ b/.clang-format @@ -4,4 +4,6 @@ BasedOnStyle: Google ColumnLimit: 100 Cpp11BracedListStyle: false # {.x = 1.0, .y = 2.0} -> { .x = 1.0, .y = 2.0 } IncludeBlocks: Preserve # sort each block of include statements instead of all +DerivePointerAlignment: false +PointerAlignment: Left ... diff --git a/assets/shaders/pbr_textured.frag b/assets/shaders/pbr_textured.frag index 8148f05..d1c725c 100644 --- a/assets/shaders/pbr_textured.frag +++ b/assets/shaders/pbr_textured.frag @@ -22,10 +22,10 @@ uniform Lights { } scene; uniform PBR_Params { - vec3 albedo; - float metallic; - float roughness; - float ao; + vec3 albedo; + float metallic; + float roughness; + float ao; } params; // Material Textures @@ -46,114 +46,114 @@ vec3 getNormalFromMap() { vec3 tangentNormal = texture(normalMap, fragTexCoords).xyz * 2.0 - 1.0; - vec3 Q1 = dFdx(fragWorldPos); - vec3 Q2 = dFdy(fragWorldPos); + vec3 Q1 = dFdx(fragWorldPos); + vec3 Q2 = dFdy(fragWorldPos); vec2 st1 = dFdx(fragTexCoords); vec2 st2 = dFdy(fragTexCoords); - vec3 N = normalize(fragNormal); - vec3 T = normalize(Q1*st2.t - Q2*st1.t); - vec3 B = -normalize(cross(N, T)); + vec3 N = normalize(fragNormal); + vec3 T = normalize(Q1 * st2.t - Q2 * st1.t); + vec3 B = -normalize(cross(N, T)); mat3 TBN = mat3(T, B, N); return normalize(TBN * tangentNormal); } void main() { - // vec3 albedo = pow(texture(albedoMap, fragTexCoords).rgb, vec3(2.2)); - vec3 albedo = params.albedo * texture(albedoMap, fragTexCoords).rgb; - float metallic = params.metallic * texture(metallicRoughnessMap, fragTexCoords).b; - float roughness = params.roughness * texture(metallicRoughnessMap, fragTexCoords).g; - float ao = texture(aoMap, fragTexCoords).r; - - // vec3 norm = normalize(fragNormal); // N - vec3 norm = getNormalFromMap(); - vec3 N = norm; - vec3 viewDir = normalize(vec3(viewPos) - fragWorldPos); // V - vec3 V = viewDir; - - vec3 F0 = vec3(0.04); - F0 = mix(F0, albedo, metallic); - - vec3 Lo = vec3(0.0); - for (int i = 0; i < 4; ++i) { - vec3 lightVec = normalize(vec3(scene.pointLights[i].position) - fragWorldPos); // L - vec3 L = lightVec; - vec3 halfway = normalize(viewDir + lightVec); // H - vec3 H = halfway; - float distance = length(vec3(scene.pointLights[i].position) - fragWorldPos); - float attenuation = 1.0 / (distance * distance); - vec3 radiance = vec3(scene.pointLights[i].color) * attenuation; - - // cook-torrance brdf - float NDF = DistributionGGX(norm, halfway, roughness); - float G = GeometrySmith(norm, viewDir, lightVec, roughness); - // vec3 F = fresnelSchlick(max(dot(halfway, viewDir), 0.0), F0); - vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0); - - vec3 numerator = NDF * G * F; - float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; - vec3 specular = numerator / denominator; - - vec3 kS = F; - - vec3 kD = vec3(1.0) - kS; - kD *= 1.0 - metallic; - - // add to outgoing radiance Lo - float NdotL = max(dot(N, L), 0.0); - Lo += (kD * albedo / PI + specular) * radiance * NdotL; - // Lo += radiance; - } + // vec3 albedo = pow(texture(albedoMap, fragTexCoords).rgb, vec3(2.2)); + vec3 albedo = params.albedo * texture(albedoMap, fragTexCoords).rgb; + float metallic = params.metallic * texture(metallicRoughnessMap, fragTexCoords).b; + float roughness = params.roughness * texture(metallicRoughnessMap, fragTexCoords).g; + float ao = texture(aoMap, fragTexCoords).r; + + // vec3 norm = normalize(fragNormal); // N + vec3 norm = getNormalFromMap(); + vec3 N = norm; + vec3 viewDir = normalize(vec3(viewPos) - fragWorldPos); // V + vec3 V = viewDir; + + vec3 F0 = vec3(0.04); + F0 = mix(F0, albedo, metallic); + + vec3 Lo = vec3(0.0); + for (int i = 0; i < 4; ++i) { + vec3 lightVec = normalize(vec3(scene.pointLights[i].position) - fragWorldPos); // L + vec3 L = lightVec; + vec3 halfway = normalize(viewDir + lightVec); // H + vec3 H = halfway; + float distance = length(vec3(scene.pointLights[i].position) - fragWorldPos); + float attenuation = 1.0 / (distance * distance); + vec3 radiance = vec3(scene.pointLights[i].color) * attenuation; + + // cook-torrance brdf + float NDF = DistributionGGX(norm, halfway, roughness); + float G = GeometrySmith(norm, viewDir, lightVec, roughness); + // vec3 F = fresnelSchlick(max(dot(halfway, viewDir), 0.0), F0); + vec3 F = fresnelSchlick(clamp(dot(H, V), 0.0, 1.0), F0); + + vec3 numerator = NDF * G * F; + float denominator = 4.0 * max(dot(N, V), 0.0) * max(dot(N, L), 0.0) + 0.0001; + vec3 specular = numerator / denominator; + + vec3 kS = F; + + vec3 kD = vec3(1.0) - kS; + kD *= 1.0 - metallic; + + // add to outgoing radiance Lo + float NdotL = max(dot(N, L), 0.0); + Lo += (kD * albedo / PI + specular) * radiance * NdotL; + // Lo += radiance; + } + + vec3 ambient = vec3(0.03) * albedo * ao; + vec3 color = ambient + Lo; //ambient + Lo; - vec3 ambient = vec3(0.03) * albedo * ao; - vec3 color = ambient + Lo; //ambient + Lo; - color = color / (color + vec3(1.0)); - color = pow(color, vec3(1.0/2.2)); - - FragColor = vec4(color, 1.0); - // FragColor = vec4(1.0); - // FragColor = vec4(scene.pointLights[0].position); - // FragColor = vec4(albedo, 1.0); - // FragColor = vec4(pbr.metallic, pbr.roughness, pbr.ao, 1.0); - // FragColor = vec4(fragTexCoords, 0.0, 1.0); + color = pow(color, vec3(1.0 / 2.2)); + + // FragColor = vec4(color, 1.0); + FragColor = vec4(1.0); + // FragColor = vec4(scene.pointLights[0].position); + // FragColor = vec4(albedo, 1.0); + // FragColor = vec4(pbr.metallic, pbr.roughness, pbr.ao, 1.0); + // FragColor = vec4(fragTexCoords, 0.0, 1.0); } /* The below are from https://learnopengl.com/PBR/Lighting */ vec3 fresnelSchlick(float cosTheta, vec3 F0) { - return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); + return F0 + (1.0 - F0) * pow(clamp(1.0 - cosTheta, 0.0, 1.0), 5.0); } float DistributionGGX(vec3 N, vec3 H, float roughness) { - float a = roughness*roughness; - float a2 = a*a; - float NdotH = max(dot(N, H), 0.0); - float NdotH2 = NdotH*NdotH; + float a = roughness * roughness; + float a2 = a * a; + float NdotH = max(dot(N, H), 0.0); + float NdotH2 = NdotH * NdotH; - float num = a2; - float denom = (NdotH2 * (a2 - 1.0) + 1.0); - denom = PI * denom * denom; + float num = a2; + float denom = (NdotH2 * (a2 - 1.0) + 1.0); + denom = PI * denom * denom; - return num / denom; + return num / denom; } float GeometrySchlickGGX(float NdotV, float roughness) { float r = (roughness + 1.0); - float k = (r*r) / 8.0; + float k = (r * r) / 8.0; - float num = NdotV; + float num = NdotV; float denom = NdotV * (1.0 - k) + k; - + return num / denom; } float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness) { float NdotV = max(dot(N, V), 0.0); float NdotL = max(dot(N, L), 0.0); - float ggx2 = GeometrySchlickGGX(NdotV, roughness); - float ggx1 = GeometrySchlickGGX(NdotL, roughness); - + float ggx2 = GeometrySchlickGGX(NdotV, roughness); + float ggx1 = GeometrySchlickGGX(NdotL, roughness); + return ggx1 * ggx2; } diff --git a/assets/shaders/pbr_textured.vert b/assets/shaders/skinned_geometry.vert index 2021691..2021691 100644 --- a/assets/shaders/pbr_textured.vert +++ b/assets/shaders/skinned_geometry.vert diff --git a/assets/shaders/static_geometry.vert b/assets/shaders/static_geometry.vert new file mode 100644 index 0000000..2021691 --- /dev/null +++ b/assets/shaders/static_geometry.vert @@ -0,0 +1,33 @@ +#version 410 core + +// Vertex attributes +layout(location = 0) in vec3 inPosition; +layout(location = 1) in vec3 inNormal; +layout(location = 2) in vec2 inTexCoords; + +uniform Camera { + mat4 view; + mat4 proj; + vec4 viewPos; +} cam; + +uniform Model { + mat4 inner; +} model; + +// Outputs +layout(location = 0) out vec3 fragWorldPos; +layout(location = 1) out vec3 fragNormal; +layout(location = 2) out vec2 fragTexCoords; + +out vec4 viewPos; + +void main() { + fragWorldPos = vec3(model.inner * vec4(inPosition, 1.0)); + fragNormal = mat3(transpose(inverse(model.inner))) * inNormal; // world-space normal + fragTexCoords = inTexCoords; + + viewPos = cam.viewPos; + + gl_Position = cam.proj * cam.view * model.inner * vec4(inPosition, 1.0); +} diff --git a/deps/glad/src/glad.c b/deps/glad/src/glad.c index faea08d..9e8481d 100644 --- a/deps/glad/src/glad.c +++ b/deps/glad/src/glad.c @@ -642,7 +642,7 @@ #include <stdlib.h> #include <string.h> -static void *get_proc(const char *namez); +static void* get_proc(const char* namez); #if defined(_WIN32) || defined(__CYGWIN__) #ifndef _WINDOWS_ @@ -651,7 +651,7 @@ static void *get_proc(const char *namez); #include <windows.h> static HMODULE libGL; -typedef void *(APIENTRYP PFNWGLGETPROCADDRESSPROC_PRIVATE)(const char *); +typedef void*(APIENTRYP PFNWGLGETPROCADDRESSPROC_PRIVATE)(const char*); static PFNWGLGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr; #ifdef _MSC_VER @@ -694,22 +694,22 @@ static void close_gl(void) { } #else #include <dlfcn.h> -static void *libGL; +static void* libGL; #if !defined(__APPLE__) && !defined(__HAIKU__) -typedef void *(APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char *); +typedef void*(APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char*); static PFNGLXGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr; #endif static int open_gl(void) { #ifdef __APPLE__ - static const char *NAMES[] = { + static const char* NAMES[] = { "../Frameworks/OpenGL.framework/OpenGL", "/Library/Frameworks/OpenGL.framework/OpenGL", "/System/Library/Frameworks/OpenGL.framework/OpenGL", "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL" }; #else - static const char *NAMES[] = { "libGL.so.1", "libGL.so" }; + static const char* NAMES[] = { "libGL.so.1", "libGL.so" }; #endif unsigned int index = 0; @@ -738,8 +738,8 @@ static void close_gl(void) { } #endif -static void *get_proc(const char *namez) { - void *result = NULL; +static void* get_proc(const char* namez) { + void* result = NULL; if (libGL == NULL) return NULL; #if !defined(__APPLE__) && !defined(__HAIKU__) @@ -749,7 +749,7 @@ static void *get_proc(const char *namez) { #endif if (result == NULL) { #if defined(_WIN32) || defined(__CYGWIN__) - result = (void *)GetProcAddress((HMODULE)libGL, namez); + result = (void*)GetProcAddress((HMODULE)libGL, namez); #else result = dlsym(libGL, namez); #endif @@ -778,15 +778,15 @@ struct gladGLversionStruct GLVersion = { 0, 0 }; static int max_loaded_major; static int max_loaded_minor; -static const char *exts = NULL; +static const char* exts = NULL; static int num_exts_i = 0; -static char **exts_i = NULL; +static char** exts_i = NULL; static int get_exts(void) { #ifdef _GLAD_IS_SOME_NEW_VERSION if (max_loaded_major < 3) { #endif - exts = (const char *)glGetString(GL_EXTENSIONS); + exts = (const char*)glGetString(GL_EXTENSIONS); #ifdef _GLAD_IS_SOME_NEW_VERSION } else { unsigned int index; @@ -794,7 +794,7 @@ static int get_exts(void) { num_exts_i = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i); if (num_exts_i > 0) { - exts_i = (char **)malloc((size_t)num_exts_i * (sizeof *exts_i)); + exts_i = (char**)malloc((size_t)num_exts_i * (sizeof *exts_i)); } if (exts_i == NULL) { @@ -802,10 +802,10 @@ static int get_exts(void) { } for (index = 0; index < (unsigned)num_exts_i; index++) { - const char *gl_str_tmp = (const char *)glGetStringi(GL_EXTENSIONS, index); + const char* gl_str_tmp = (const char*)glGetStringi(GL_EXTENSIONS, index); size_t len = strlen(gl_str_tmp); - char *local_str = (char *)malloc((len + 1) * sizeof(char)); + char* local_str = (char*)malloc((len + 1) * sizeof(char)); if (local_str != NULL) { memcpy(local_str, gl_str_tmp, (len + 1) * sizeof(char)); } @@ -820,20 +820,20 @@ static void free_exts(void) { if (exts_i != NULL) { int index; for (index = 0; index < num_exts_i; index++) { - free((char *)exts_i[index]); + free((char*)exts_i[index]); } - free((void *)exts_i); + free((void*)exts_i); exts_i = NULL; } } -static int has_ext(const char *ext) { +static int has_ext(const char* ext) { #ifdef _GLAD_IS_SOME_NEW_VERSION if (max_loaded_major < 3) { #endif - const char *extensions; - const char *loc; - const char *terminator; + const char* extensions; + const char* loc; + const char* terminator; extensions = exts; if (extensions == NULL || ext == NULL) { return 0; @@ -856,7 +856,7 @@ static int has_ext(const char *ext) { int index; if (exts_i == NULL) return 0; for (index = 0; index < num_exts_i; index++) { - const char *e = exts_i[index]; + const char* e = exts_i[index]; if (exts_i[index] != NULL && strcmp(e, ext) == 0) { return 1; @@ -10708,10 +10708,10 @@ static void find_coreGL(void) { */ int i, major, minor; - const char *version; - const char *prefixes[] = { "OpenGL ES-CM ", "OpenGL ES-CL ", "OpenGL ES ", NULL }; + const char* version; + const char* prefixes[] = { "OpenGL ES-CM ", "OpenGL ES-CL ", "OpenGL ES ", NULL }; - version = (const char *)glGetString(GL_VERSION); + version = (const char*)glGetString(GL_VERSION); if (!version) return; for (i = 0; prefixes[i]; i++) { diff --git a/examples/skinned_animation/ex_skinned_animation.c b/examples/skinned_animation/ex_skinned_animation.c index 672e0d2..7a44160 100644 --- a/examples/skinned_animation/ex_skinned_animation.c +++ b/examples/skinned_animation/ex_skinned_animation.c @@ -7,6 +7,8 @@ #include "log.h" #include "maths.h" #include "maths_types.h" +#include "pbr.h" +#include "render.h" #include "render_types.h" int main() { @@ -19,6 +21,8 @@ int main() { ModelHandle handle = ModelLoad_gltf("assets/models/gltf/SimpleSkin/glTF/SimpleSkin.gltf", false); Model* simple_skin = MODEL_GET(handle); + RenderEnt_darray* rend_ents = RenderEnt_darray_new(1); + // 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); @@ -67,8 +71,12 @@ int main() { // Transform tf = transform_create(VEC3_ZERO, quat_ident(), 1.0); // TODO: Drawing should still just use the PBR pipeline + ModelExtractRenderEnts(rend_ents, handle, mat4_translation(vec3(0, -1, 0)), 0); // draw_skinned_model(&core->renderer, &game.camera, simple_skin, tf, &our_scene); + Render_RenderEntities(rend_ents->data, rend_ents->len); + + RenderEnt_darray_clear(rend_ents); Frame_End(); } diff --git a/src/animation.h b/src/animation.h index 8bf3940..08ee92a 100644 --- a/src/animation.h +++ b/src/animation.h @@ -3,6 +3,7 @@ #include "darray.h" #include "defines.h" #include "maths_types.h" +#include "mem.h" typedef enum Interpolation { INTERPOLATION_STEP, @@ -46,6 +47,7 @@ typedef u32 JointIdx; typedef struct Armature { char* label; + arena arena; Joint_darray* joints; } Armature; @@ -79,6 +81,10 @@ typedef struct AnimationClip { AnimationSampler* scale; AnimationSampler* weights; } AnimationClip; +#ifndef TYPED_ANIM_CLIP_ARRAY +KITC_DECL_TYPED_ARRAY(AnimationClip); +#define TYPED_ANIM_CLIP_ARRAY +#endif typedef struct SkinnedAnimation { Mat4* joint_matrices; diff --git a/src/core/camera.c b/src/core/camera.c index 7bddb7e..c996d7d 100644 --- a/src/core/camera.c +++ b/src/core/camera.c @@ -12,7 +12,7 @@ Camera Camera_Create(Vec3 pos, Vec3 front, Vec3 up, f32 fov) { return c; } -Mat4 Camera_ViewProj(Camera *c, f32 lens_height, f32 lens_width, Mat4 *out_view, Mat4 *out_proj) { +Mat4 Camera_ViewProj(Camera* c, f32 lens_height, f32 lens_width, Mat4* out_view, Mat4* out_proj) { Mat4 proj = mat4_perspective(c->fov, lens_width / lens_height, 0.1, 1000.0); Vec3 camera_direction = vec3_add(c->position, c->front); Mat4 view = mat4_look_at(c->position, camera_direction, c->up); @@ -25,7 +25,7 @@ Mat4 Camera_ViewProj(Camera *c, f32 lens_height, f32 lens_width, Mat4 *out_view, return mat4_mult(view, proj); } -void FlyCamera_Update(Camera *camera) { +void FlyCamera_Update(Camera* camera) { static f32 yaw = 0.0; static f32 pitch = 0.0; @@ -17,9 +17,9 @@ #define WHT "\e[0;37m" #define CRESET "\e[0m" -static const char *level_strings[6] = { "[FATAL]: ", "[ERROR]: ", "[WARN]: ", +static const char* level_strings[6] = { "[FATAL]: ", "[ERROR]: ", "[WARN]: ", "[INFO]: ", "[DEBUG]: ", "[TRACE]: " }; -static const char *level_colours[6] = { RED, RED, YEL, BLU, CYN, MAG }; +static const char* level_colours[6] = { RED, RED, YEL, BLU, CYN, MAG }; bool logger_init() { // TODO: create log file @@ -30,7 +30,7 @@ void logger_shutdown() { // does nothing right now } -void log_output(log_level level, const char *message, ...) { +void log_output(log_level level, const char* message, ...) { char out_message[32000]; memset(out_message, 0, sizeof(out_message)); @@ -49,7 +49,7 @@ void log_output(log_level level, const char *message, ...) { printf("%s", out_message2); } -void report_assertion_failure(const char *expression, const char *message, const char *file, +void report_assertion_failure(const char* expression, const char* message, const char* file, int line) { log_output(LOG_LEVEL_FATAL, "Assertion failure: %s, message: '%s', in file: %s, on line %d\n", expression, message, file, line); @@ -36,7 +36,7 @@ void logger_shutdown(); // TODO: macro that outputs logger macros for a specific subsystem or string prefix e.g. "MEMORY" -> // logs now have more context potentially have line numbers too? -void log_output(log_level level, const char *message, ...); +void log_output(log_level level, const char* message, ...); #define FATAL(message, ...) log_output(LOG_LEVEL_FATAL, message, ##__VA_ARGS__) #define ERROR(message, ...) log_output(LOG_LEVEL_ERROR, message, ##__VA_ARGS__) @@ -57,7 +57,7 @@ void log_output(log_level level, const char *message, ...); // TODO: Move this to an asserts file -void report_assertion_failure(const char *expression, const char *message, const char *file, +void report_assertion_failure(const char* expression, const char* message, const char* file, int line); #define CASSERT(expr) \ diff --git a/src/logos/threadpool.c b/src/logos/threadpool.c index bf54d08..0e82d98 100644 --- a/src/logos/threadpool.c +++ b/src/logos/threadpool.c @@ -6,8 +6,8 @@ #include "log.h" #include "ring_queue.h" -static void *worker_factory(void *arg) { - threadpool_worker *worker = arg; +static void* worker_factory(void* arg) { + threadpool_worker* worker = arg; // INFO("Starting job thread %d", worker->id); // Run forever, waiting for jobs. @@ -50,7 +50,7 @@ static void *worker_factory(void *arg) { return NULL; } -bool threadpool_create(threadpool *pool, u8 thread_count, u32 queue_size) { +bool threadpool_create(threadpool* pool, u8 thread_count, u32 queue_size) { INFO("Threadpool init"); pool->next_task_id = 0; pool->context = NULL; @@ -84,13 +84,13 @@ bool threadpool_create(threadpool *pool, u8 thread_count, u32 queue_size) { return true; } -bool threadpool_add_task(threadpool *pool, tpool_task_start do_task, +bool threadpool_add_task(threadpool* pool, tpool_task_start do_task, tpool_task_on_complete on_success, tpool_task_on_complete on_fail, - bool buffer_result_for_main_thread, void *param_data, u32 param_data_size, + bool buffer_result_for_main_thread, void* param_data, u32 param_data_size, u32 result_data_size) { - void *result_data = malloc(result_data_size); + void* result_data = malloc(result_data_size); - task *work_task = malloc(sizeof(task)); + task* work_task = malloc(sizeof(task)); work_task->task_id = 0; work_task->do_task = do_task; work_task->on_success = on_success; @@ -123,11 +123,11 @@ bool threadpool_add_task(threadpool *pool, tpool_task_start do_task, return true; } -void threadpool_process_results(threadpool *pool, int _num_to_process) { +void threadpool_process_results(threadpool* pool, int _num_to_process) { pthread_mutex_lock(&pool->mutex); size_t num_results = deferred_task_result_darray_len(pool->results); if (num_results > 0) { - u32 _size = ((deferred_task_result *)pool->results->data)[num_results].result_data_size; + u32 _size = ((deferred_task_result*)pool->results->data)[num_results].result_data_size; deferred_task_result res; deferred_task_result_darray_pop(pool->results, &res); pthread_mutex_unlock(&pool->mutex); @@ -138,4 +138,4 @@ void threadpool_process_results(threadpool *pool, int _num_to_process) { } } -void threadpool_set_ctx(threadpool *pool, void *ctx) { pool->context = ctx; }
\ No newline at end of file +void threadpool_set_ctx(threadpool* pool, void* ctx) { pool->context = ctx; }
\ No newline at end of file diff --git a/src/logos/threadpool.h b/src/logos/threadpool.h index 2cd70fd..6390a38 100644 --- a/src/logos/threadpool.h +++ b/src/logos/threadpool.h @@ -15,20 +15,20 @@ struct threadpool; typedef struct threadpool threadpool; typedef struct task_globals { - threadpool *pool; - void *ctx; + threadpool* pool; + void* ctx; } task_globals; /* function pointer */ -typedef bool (*tpool_task_start)(void *, void *); +typedef bool (*tpool_task_start)(void*, void*); /* function pointer */ -typedef void (*tpool_task_on_complete)(task_globals *, void *); +typedef void (*tpool_task_on_complete)(task_globals*, void*); typedef struct threadpool_worker { u16 id; pthread_t thread; - threadpool *pool; // pointer back to the pool so we can get the mutex and cond + threadpool* pool; // pointer back to the pool so we can get the mutex and cond } threadpool_worker; typedef enum tpool_task_status { @@ -42,9 +42,9 @@ typedef struct tpool_task { tpool_task_on_complete on_failure; bool buffer_result_for_main_thread; /** @brief a pointer to the parameters data that will be passed into the task. */ - void *params; + void* params; u32 param_size; - void *result_data; + void* result_data; u32 result_data_size; } task; @@ -53,7 +53,7 @@ typedef struct deferred_task_result { tpool_task_on_complete callback; u32 result_data_size; // this gets passed to the void* argument of `tpool_task_on_complete` - void *result_data; + void* result_data; } deferred_task_result; #ifndef TYPED_TASK_RESULT_ARRAY @@ -62,14 +62,14 @@ KITC_DECL_TYPED_ARRAY(deferred_task_result) // creates "deferred_task_result_da #endif struct threadpool { - ring_queue *task_queue; + ring_queue* task_queue; pthread_mutex_t mutex; pthread_cond_t has_tasks; threadpool_worker workers[MAX_NUM_THREADS]; - deferred_task_result_darray *results; + deferred_task_result_darray* results; u64 next_task_id; - void *context; + void* context; }; /** @@ -77,20 +77,20 @@ struct threadpool { * @param thread_count how many threads to spawn * @param queue_size max size of task queue */ -bool threadpool_create(threadpool *pool, u8 thread_count, u32 queue_size); -void threadpool_destroy(threadpool *pool); +bool threadpool_create(threadpool* pool, u8 thread_count, u32 queue_size); +void threadpool_destroy(threadpool* pool); /** @brief set a context variable for the threadpool that task data has access to */ -void threadpool_set_ctx(threadpool *pool, void *ctx); +void threadpool_set_ctx(threadpool* pool, void* ctx); /** * @brief Add a task to the threadpool */ -bool threadpool_add_task(threadpool *pool, tpool_task_start do_task, +bool threadpool_add_task(threadpool* pool, tpool_task_start do_task, tpool_task_on_complete on_success, tpool_task_on_complete on_fail, - bool buffer_result_for_main_thread, void *param_data, u32 param_data_size, + bool buffer_result_for_main_thread, void* param_data, u32 param_data_size, u32 result_data_size); -void threadpool_process_results(threadpool *pool, int num_to_process); +void threadpool_process_results(threadpool* pool, int num_to_process); u32 Tpool_GetNumWorkers(); // how many threads are we using
\ No newline at end of file diff --git a/src/maths/maths.c b/src/maths/maths.c index 1c5a91a..19052fe 100644 --- a/src/maths/maths.c +++ b/src/maths/maths.c @@ -26,7 +26,7 @@ Mat4 mat4_ident() { return (Mat4){ .data = { 1.0, 0., 0., 0., 0., 1., 0., 0., 0., 0., 1., 0., 0., 0., 0., 1.0 } }; } -Mat4 transform_to_mat(Transform *tf) { +Mat4 transform_to_mat(Transform* tf) { Mat4 scale = mat4_scale(tf->scale); Mat4 rotation = mat4_rotation(tf->rotation); Mat4 translation = mat4_translation(tf->position); diff --git a/src/maths/maths.h b/src/maths/maths.h index fc23517..e77b81a 100644 --- a/src/maths/maths.h +++ b/src/maths/maths.h @@ -178,9 +178,9 @@ static Mat4 mat4_rotation(Quat rotation) { static Mat4 mat4_mult(Mat4 lhs, Mat4 rhs) { Mat4 out_matrix = mat4_ident(); - const f32 *m1_ptr = lhs.data; - const f32 *m2_ptr = rhs.data; - f32 *dst_ptr = out_matrix.data; + const f32* m1_ptr = lhs.data; + const f32* m2_ptr = rhs.data; + f32* dst_ptr = out_matrix.data; for (i32 i = 0; i < 4; ++i) { for (i32 j = 0; j < 4; ++j) { @@ -311,7 +311,7 @@ static Transform transform_create(Vec3 pos, Quat rot, Vec3 scale) { return (Transform){ .position = pos, .rotation = rot, .scale = scale, .is_dirty = true }; } -Mat4 transform_to_mat(Transform *tf); +Mat4 transform_to_mat(Transform* tf); // --- Sizing asserts diff --git a/src/maths/primitives.c b/src/maths/primitives.c index 13fa81b..05c31ca 100644 --- a/src/maths/primitives.c +++ b/src/maths/primitives.c @@ -31,15 +31,15 @@ Geometry Geo_CreatePlane(f32x2 extents, u32 tiling_u, u32 tiling_v) { vert_pos[i].x *= extents.x; vert_pos[i].z *= extents.y; } - VERT_3D(vertices, vert_pos[0], VEC3_Y, vec2(0, 0)); // back left - VERT_3D(vertices, vert_pos[1], VEC3_Y, vec2(1 * tiling_u, 0 * tiling_v)); // back right - VERT_3D(vertices, vert_pos[2], VEC3_Y, vec2(0, 1 * tiling_v)); // front left - VERT_3D(vertices, vert_pos[3], VEC3_Y, vec2(1 * tiling_u, 1 * tiling_v)); // front right + VERT_3D(vertices, vert_pos[0], VEC3_Y, vec2(0, 0)); // back left + VERT_3D(vertices, vert_pos[1], VEC3_Y, vec2(1 * tiling_u, 0 * tiling_v)); // back right + VERT_3D(vertices, vert_pos[2], VEC3_Y, vec2(0, 1 * tiling_v)); // front left + VERT_3D(vertices, vert_pos[3], VEC3_Y, vec2(1 * tiling_u, 1 * tiling_v)); // front right // push_triangle(indices, 0, 1, 2); // push_triangle(indices, 2, 1, 3); push_triangle(indices, 2, 1, 0); - push_triangle(indices, 1,2,3); + push_triangle(indices, 1, 2, 3); for (int i = 0; i < 4; i++) { printf("Vertex %d: (%f, %f, %f)\n", i, vert_pos[i].x, vert_pos[i].y, vert_pos[i].z); diff --git a/src/physics.h b/src/physics.h index 3485d1b..134f08b 100644 --- a/src/physics.h +++ b/src/physics.h @@ -29,16 +29,16 @@ void physics_system_update(physics_world* phys_world, f64 deltatime); /** @brief Oriented Bounding Box */ typedef struct OBB { - Vec3 center; - Bbox_3D bbox; - Quat rotation; + Vec3 center; + Bbox_3D bbox; + Quat rotation; } OBB; PUB void Debug_DrawOBB(OBB obb); /** @brief generic collider structure */ typedef struct Collider { - u64 id; // ? Replace with handle? - OBB shape; // NOTE: We're only supporting the one collider type for now + u64 id; // ? Replace with handle? + OBB shape; // NOTE: We're only supporting the one collider type for now bool on_ground; } Collider; diff --git a/src/platform/file.c b/src/platform/file.c index ea69e20..91daa4f 100644 --- a/src/platform/file.c +++ b/src/platform/file.c @@ -10,8 +10,8 @@ #include "mem.h" #include "str.h" -const char *string_from_file(const char *path) { - FILE *f = fopen(path, "rb"); +const char* string_from_file(const char* path) { + FILE* f = fopen(path, "rb"); if (f == NULL) { ERROR("Error reading file: %s. errno: %d", path, errno); return NULL; @@ -24,7 +24,7 @@ const char *string_from_file(const char *path) { long fsize = ftell(f); rewind(f); - char *string = malloc(fsize + 1); + char* string = malloc(fsize + 1); fread(string, fsize, 1, f); fclose(f); @@ -33,11 +33,11 @@ const char *string_from_file(const char *path) { return string; } -str8_opt str8_from_file(arena *a, Str8 path) { - char *p = cstr(a, path); +str8_opt str8_from_file(arena* a, Str8 path) { + char* p = cstr(a, path); str8_opt result = { .has_value = false }; - FILE *f = fopen(p, "rb"); + FILE* f = fopen(p, "rb"); if (f == NULL) { ERROR("Error reading file: %s. errno: %d", path, errno); return result; @@ -50,7 +50,7 @@ str8_opt str8_from_file(arena *a, Str8 path) { long fsize = ftell(f); rewind(f); - u8 *raw = arena_alloc(a, fsize + 1); + u8* raw = arena_alloc(a, fsize + 1); Str8 contents = Str8_create(raw, fsize); contents.buf[contents.len] = '\0'; @@ -62,8 +62,8 @@ str8_opt str8_from_file(arena *a, Str8 path) { return result; } -FileData load_spv_file(const char *path) { - FILE *f = fopen(path, "rb"); +FileData load_spv_file(const char* path) { + FILE* f = fopen(path, "rb"); if (f == NULL) { perror("Error opening file"); return (FileData){ NULL, 0 }; @@ -73,7 +73,7 @@ FileData load_spv_file(const char *path) { long fsize = ftell(f); rewind(f); - char *data = (char *)malloc(fsize); + char* data = (char*)malloc(fsize); if (data == NULL) { perror("Memory allocation failed"); fclose(f); diff --git a/src/ral/backends/opengl/backend_opengl.h b/src/ral/backends/opengl/backend_opengl.h index 805914e..7bd1b81 100644 --- a/src/ral/backends/opengl/backend_opengl.h +++ b/src/ral/backends/opengl/backend_opengl.h @@ -20,12 +20,12 @@ typedef struct GPU_Device { } GPU_Device; typedef struct GPU_PipelineLayout { - void *pad; + void* pad; } GPU_PipelineLayout; typedef struct GPU_Pipeline { u32 shader_id; - GPU_Renderpass *renderpass; + GPU_Renderpass* renderpass; VertexDescription vertex_desc; BufferHandle uniform_bindings[MAX_PIPELINE_UNIFORM_BUFFERS]; u32 uniform_count; @@ -38,11 +38,11 @@ typedef struct GPU_Renderpass { } GPU_Renderpass; typedef struct GPU_CmdEncoder { - GPU_Pipeline *pipeline; + GPU_Pipeline* pipeline; } GPU_CmdEncoder; // Recording typedef struct GPU_CmdBuffer { - void *pad; + void* pad; } GPU_CmdBuffer; // Ready for submission typedef struct GPU_Buffer { @@ -55,7 +55,7 @@ typedef struct GPU_Buffer { u32 vao; u32 ubo_binding_point; }; // Optional - char *name; + char* name; u64 size; } GPU_Buffer; @@ -68,43 +68,42 @@ typedef struct opengl_support { u32 pad; } opengl_support; - -void uniform_vec3f(u32 program_id, const char *uniform_name, Vec3 *value); -void uniform_f32(u32 program_id, const char *uniform_name, f32 value); -void uniform_i32(u32 program_id, const char *uniform_name, i32 value); -void uniform_mat4f(u32 program_id, const char *uniform_name, Mat4 *value); +void uniform_vec3f(u32 program_id, const char* uniform_name, Vec3* value); +void uniform_f32(u32 program_id, const char* uniform_name, f32 value); +void uniform_i32(u32 program_id, const char* uniform_name, i32 value); +void uniform_mat4f(u32 program_id, const char* uniform_name, Mat4* value); typedef enum GlCommandType { - GLCMD_DRAW, - GLCMD_DRAW_INDEXED, - GLCMD_BIND_VBUF, - GLCMD_BIND_IBUF, - GLCMD_SET_PROGRAM, + GLCMD_DRAW, + GLCMD_DRAW_INDEXED, + GLCMD_BIND_VBUF, + GLCMD_BIND_IBUF, + GLCMD_SET_PROGRAM, } GlCommandType; typedef struct GlCommand { - GlCommandType cmd_type; - union { - struct { - PrimitiveTopology topology; - u32 start_vertex; - u32 vertex_count; - // TODO: instance - } draw; - struct { - PrimitiveTopology topology; - u32 index_count; - } draw_indexed; - struct { - u32 buffer_id; - } bind_vbuf; - struct { - u32 buffer_id; - } bind_ibuf; - struct { - u32 program_id; - } set_program; - } data; + GlCommandType cmd_type; + union { + struct { + PrimitiveTopology topology; + u32 start_vertex; + u32 vertex_count; + // TODO: instance + } draw; + struct { + PrimitiveTopology topology; + u32 index_count; + } draw_indexed; + struct { + u32 buffer_id; + } bind_vbuf; + struct { + u32 buffer_id; + } bind_ibuf; + struct { + u32 program_id; + } set_program; + } data; } GlCommand; #endif diff --git a/src/ral/backends/opengl/opengl_helpers.h b/src/ral/backends/opengl/opengl_helpers.h index b73eaea..706e2a0 100644 --- a/src/ral/backends/opengl/opengl_helpers.h +++ b/src/ral/backends/opengl/opengl_helpers.h @@ -140,11 +140,16 @@ static GLenum opengl_tex_type(GPU_TextureType tex_type) { static GLenum opengl_prim_topology(PrimitiveTopology t) { switch (t) { - case CEL_POINT: return GL_POINT; - case CEL_LINE: return GL_LINES; - case CEL_LINE_STRIP: return GL_LINE_STRIP; - case CEL_TRI: return GL_TRIANGLES; - case CEL_TRI_STRIP: return GL_TRIANGLE_STRIP; + case CEL_POINT: + return GL_POINT; + case CEL_LINE: + return GL_LINES; + case CEL_LINE_STRIP: + return GL_LINE_STRIP; + case CEL_TRI: + return GL_TRIANGLES; + case CEL_TRI_STRIP: + return GL_TRIANGLE_STRIP; case PRIMITIVE_TOPOLOGY_COUNT: WARN("Invalid PrimitiveTopology value"); break; diff --git a/src/ral/ral_impl.h b/src/ral/ral_impl.h index 3374d91..16c9767 100644 --- a/src/ral/ral_impl.h +++ b/src/ral/ral_impl.h @@ -62,7 +62,8 @@ PUB void GPU_TextureDestroy(TextureHandle handle); PUB void GPU_TextureUpload(TextureHandle handle, size_t n_bytes, const void* data); // --- Data copy commands -PUB void GPU_EncodeCopyBufToBuf(GPU_CmdEncoder* encoder, BufferHandle src, u64 src_offset, BufferHandle dst, u64 dst_offset, u64 copy_size); +PUB void GPU_EncodeCopyBufToBuf(GPU_CmdEncoder* encoder, BufferHandle src, u64 src_offset, + BufferHandle dst, u64 dst_offset, u64 copy_size); // PUB void GPU_EncodeCopyBufToTex(GPU_CmdEncoder* encoder, BufferHandle src, TextureHandle dst, // u32 x_offset, u32 y_offset, u32 width, u32 height, const void* data); @@ -81,7 +82,8 @@ PUB void GPU_EncodeSetVertexBuffer(GPU_CmdEncoder* encoder, BufferHandle buf); PUB void GPU_EncodeSetIndexBuffer(GPU_CmdEncoder* encoder, BufferHandle buf); PUB void GPU_EncodeDraw(GPU_CmdEncoder* encoder, PrimitiveTopology topology, u64 count); -PUB void GPU_EncodeDrawIndexed(GPU_CmdEncoder* encoder, PrimitiveTopology topology, u64 index_count); +PUB void GPU_EncodeDrawIndexed(GPU_CmdEncoder* encoder, PrimitiveTopology topology, + u64 index_count); // convenience versions of the above PUB void GPU_EncodeDrawTris(GPU_CmdEncoder* encoder, u64 count); PUB void GPU_EncodeDrawIndexedTris(GPU_CmdEncoder* encoder, u64 index_count); diff --git a/src/ral/ral_types.h b/src/ral/ral_types.h index 7c83af6..1f98e88 100644 --- a/src/ral/ral_types.h +++ b/src/ral/ral_types.h @@ -243,22 +243,19 @@ typedef enum PrimitiveTopology { typedef enum CullMode { CULL_BACK_FACE, CULL_FRONT_FACE, CULL_COUNT } CullMode; -typedef enum Winding { - WINDING_CCW, - WINDING_CW -} Winding; +typedef enum Winding { WINDING_CCW, WINDING_CW } Winding; // based on https://registry.khronos.org/OpenGL-Refpages/gl4/html/glDepthFunc.xhtml typedef enum CompareFunc { - COMPARE_NEVER, - COMPARE_LESS, - COMPARE_EQUAL, - COMPARE_LESS_EQUAL, - COMPARE_GREATER, - COMPARE_NOT_EQUAL, - COMPARE_GREATER_EQUAL, - COMPARE_ALWAYS, - COMPARE_COUNT + COMPARE_NEVER, + COMPARE_LESS, + COMPARE_EQUAL, + COMPARE_LESS_EQUAL, + COMPARE_GREATER, + COMPARE_NOT_EQUAL, + COMPARE_GREATER_EQUAL, + COMPARE_ALWAYS, + COMPARE_COUNT } CompareFunc; typedef struct GraphicsPipelineDesc { diff --git a/src/render/archive/backends/opengl/backend_opengl.h b/src/render/archive/backends/opengl/backend_opengl.h index 73a19ed..14b44af 100644 --- a/src/render/archive/backends/opengl/backend_opengl.h +++ b/src/render/archive/backends/opengl/backend_opengl.h @@ -17,11 +17,11 @@ typedef struct gpu_swapchain { typedef struct gpu_device { } gpu_device; typedef struct gpu_pipeline_layout { - void *pad + void* pad } gpu_pipeline_layout; typedef struct gpu_pipeline { u32 shader_id; - gpu_renderpass *renderpass; + gpu_renderpass* renderpass; vertex_description vertex_desc; buffer_handle uniform_bindings[MAX_PIPELINE_UNIFORM_BUFFERS]; u32 uniform_count; @@ -32,10 +32,10 @@ typedef struct gpu_renderpass { gpu_renderpass_desc description; } gpu_renderpass; typedef struct gpu_cmd_encoder { - gpu_pipeline *pipeline; + gpu_pipeline* pipeline; } gpu_cmd_encoder; // Recording typedef struct gpu_cmd_buffer { - void *pad; + void* pad; } gpu_cmd_buffer; // Ready for submission typedef struct gpu_buffer { @@ -48,21 +48,21 @@ typedef struct gpu_buffer { u32 vao; u32 ubo_binding_point }; // Optional - char *name; + char* name; u64 size; } gpu_buffer; typedef struct gpu_texture { u32 id; - void *pad; + void* pad; } gpu_texture; typedef struct opengl_support { } opengl_support; -u32 shader_create_separate(const char *vert_shader, const char *frag_shader); +u32 shader_create_separate(const char* vert_shader, const char* frag_shader); -void uniform_vec3f(u32 program_id, const char *uniform_name, vec3 *value); -void uniform_f32(u32 program_id, const char *uniform_name, f32 value); -void uniform_i32(u32 program_id, const char *uniform_name, i32 value); -void uniform_mat4f(u32 program_id, const char *uniform_name, mat4 *value); +void uniform_vec3f(u32 program_id, const char* uniform_name, vec3* value); +void uniform_f32(u32 program_id, const char* uniform_name, f32 value); +void uniform_i32(u32 program_id, const char* uniform_name, i32 value); +void uniform_mat4f(u32 program_id, const char* uniform_name, mat4* value); #endif diff --git a/src/render/immdraw.h b/src/render/immdraw.h index aa1847b..b205129 100644 --- a/src/render/immdraw.h +++ b/src/render/immdraw.h @@ -37,7 +37,8 @@ PUB void Immdraw_TransformGizmo(Transform tf, f32 size); // --- Internal -void Immdraw_Primitive(Transform tf, PrimitiveTopology topology, f32 size, Vec4 colour, bool wireframe, Mesh mesh); +void Immdraw_Primitive(Transform tf, PrimitiveTopology topology, f32 size, Vec4 colour, + bool wireframe, Mesh mesh); Mesh GenBboxMesh(); diff --git a/src/render/pbr.c b/src/render/pbr.c index fbdacac..57ca1d8 100644 --- a/src/render/pbr.c +++ b/src/render/pbr.c @@ -15,7 +15,7 @@ void PBR_Init(PBR_Storage* storage) { INFO("PBR shaders init"); storage->pbr_pass = PBR_RPassCreate(); - storage->pbr_pipeline = PBR_PipelineCreate(storage->pbr_pass); + PBR_PipelinesCreate(storage, storage->pbr_pass); } GPU_Renderpass* PBR_RPassCreate() { @@ -23,45 +23,72 @@ GPU_Renderpass* PBR_RPassCreate() { return GPU_Renderpass_Create(desc); } -GPU_Pipeline* PBR_PipelineCreate(GPU_Renderpass* rpass) { - arena scratch = arena_create(malloc(1024 * 1024), 1024 * 1024); - - const char* vert_path = "assets/shaders/pbr_textured.vert"; - const char* frag_path = "assets/shaders/pbr_textured.frag"; - // Str8 vert_path = str8("assets/shaders/pbr_textured.vert"); - // Str8 frag_path = str8("assets/shaders/pbr_textured.frag"); - // str8_opt vertex_shader = str8_from_file(&scratch, vert_path); - // str8_opt fragment_shader = str8_from_file(&scratch, frag_path); - // if (!vertex_shader.has_value || !fragment_shader.has_value) { - // ERROR_EXIT("Failed to load shaders from disk") - // } - char* vert_shader = string_from_file(vert_path); - char* frag_shader = string_from_file(frag_path); - - ShaderDataLayout camera_data = Binding_Camera_GetLayout(NULL); - ShaderDataLayout model_data = Binding_Model_GetLayout(NULL); - ShaderDataLayout material_data = PBRMaterial_GetLayout(NULL); - ShaderDataLayout lights_data = Binding_Lights_GetLayout(NULL); - - GraphicsPipelineDesc desc = { - .debug_name = "PBR Pipeline", - .vertex_desc = static_3d_vertex_description(), - .data_layouts = {camera_data,model_data,material_data, lights_data }, - .data_layouts_count = 4, - .vs = { .debug_name = "PBR (textured) Vertex Shader", - .filepath = str8(vert_path), - // .code = vertex_shader.contents - .code = vert_shader - }, - .fs = { .debug_name = "PBR (textured) Fragment Shader", - .filepath = str8(frag_path), - .code = frag_shader - // .code = fragment_shader.contents, - }, - .depth_test = true, - .wireframe = false, - }; - return GPU_GraphicsPipeline_Create(desc, rpass); +void PBR_PipelinesCreate(PBR_Storage* storage, GPU_Renderpass* rpass) { + // Static + { + const char* vert_path = "assets/shaders/static_geometry.vert"; + const char* frag_path = "assets/shaders/pbr_textured.frag"; + char* vert_shader = string_from_file(vert_path); + char* frag_shader = string_from_file(frag_path); + + ShaderDataLayout camera_data = Binding_Camera_GetLayout(NULL); + ShaderDataLayout model_data = Binding_Model_GetLayout(NULL); + ShaderDataLayout material_data = PBRMaterial_GetLayout(NULL); + ShaderDataLayout lights_data = Binding_Lights_GetLayout(NULL); + + GraphicsPipelineDesc desc = { + .debug_name = "PBR (Static) Pipeline", + .vertex_desc = static_3d_vertex_description(), + .data_layouts = { camera_data, model_data, material_data, lights_data }, + .data_layouts_count = 4, + .vs = { .debug_name = "PBR (textured) Vertex Shader", + .filepath = str8(vert_path), + .code = vert_shader }, + .fs = { .debug_name = "PBR (textured) Fragment Shader", + .filepath = str8(frag_path), + .code = frag_shader }, + .depth_test = true, + .wireframe = true, + }; + storage->pbr_static_pipeline = GPU_GraphicsPipeline_Create(desc, rpass); + } + + // Skinned + { + const char* vert_path = "assets/shaders/skinned_geometry.vert"; + const char* frag_path = "assets/shaders/pbr_textured.frag"; + char* vert_shader = string_from_file(vert_path); + char* frag_shader = string_from_file(frag_path); + + ShaderDataLayout camera_data = Binding_Camera_GetLayout(NULL); + ShaderDataLayout model_data = Binding_Model_GetLayout(NULL); + ShaderDataLayout material_data = PBRMaterial_GetLayout(NULL); + ShaderDataLayout lights_data = Binding_Lights_GetLayout(NULL); + + VertexDescription vertex_desc = { .debug_label = "Skinned vertices", + .use_full_vertex_size = true }; + VertexDesc_AddAttr(&vertex_desc, "inPos", ATTR_F32x3); + VertexDesc_AddAttr(&vertex_desc, "inNormal", ATTR_F32x3); + VertexDesc_AddAttr(&vertex_desc, "inTexCoords", ATTR_F32x2); + VertexDesc_AddAttr(&vertex_desc, "inBoneIndices", ATTR_I32x4); + VertexDesc_AddAttr(&vertex_desc, "inWeights", ATTR_F32x4); + + GraphicsPipelineDesc desc = { + .debug_name = "PBR (Skinned) Pipeline", + .vertex_desc = vertex_desc, + .data_layouts = { camera_data, model_data, material_data, lights_data }, + .data_layouts_count = 4, + .vs = { .debug_name = "PBR (textured) Vertex Shader", + .filepath = str8(vert_path), + .code = vert_shader }, + .fs = { .debug_name = "PBR (textured) Fragment Shader", + .filepath = str8(frag_path), + .code = frag_shader }, + .depth_test = true, + .wireframe = true, + }; + storage->pbr_skinned_pipeline = GPU_GraphicsPipeline_Create(desc, rpass); + } } void PBR_Execute(PBR_Storage* storage, Camera camera, TextureHandle shadowmap_tex, @@ -75,7 +102,7 @@ void PBR_Execute(PBR_Storage* storage, Camera camera, TextureHandle shadowmap_te GPU_CmdEncoder* enc = GPU_GetDefaultEncoder(); GPU_CmdEncoder_BeginRender(enc, storage->pbr_pass); - GPU_EncodeBindPipeline(enc, storage->pbr_pipeline); + GPU_EncodeBindPipeline(enc, storage->pbr_static_pipeline); // Feed shader data Mat4 view, proj; diff --git a/src/render/pbr.h b/src/render/pbr.h index d7b660b..5a21533 100644 --- a/src/render/pbr.h +++ b/src/render/pbr.h @@ -16,7 +16,8 @@ /** @brief Holds data for the PBR pipeline */ typedef struct PBR_Storage { GPU_Renderpass* pbr_pass; - GPU_Pipeline* pbr_pipeline; + GPU_Pipeline* pbr_static_pipeline; + GPU_Pipeline* pbr_skinned_pipeline; } PBR_Storage; typedef struct PBRMaterialUniforms { @@ -62,7 +63,8 @@ PUB ShaderDataLayout PBRMaterial_GetLayout(void* data); GPU_Renderpass* PBR_RPassCreate(); /** @brief Create the PBR Renderpass */ -GPU_Pipeline* PBR_PipelineCreate(GPU_Renderpass* rpass); /** @brief Create the PBR Pipeline */ +void PBR_PipelinesCreate(PBR_Storage* storage, + GPU_Renderpass* rpass); /** @brief Create PBR Pipelines */ void PBR_Execute(PBR_Storage* storage, Camera camera, TextureHandle shadowmap_tex, RenderEnt* entities, size_t entity_count); diff --git a/src/render/render.c b/src/render/render.c index 4e7a60c..af636a8 100644 --- a/src/render/render.c +++ b/src/render/render.c @@ -283,6 +283,11 @@ PUB MaterialHandle Material_Insert(Material* material) { } Mesh* Mesh_Get(MeshHandle handle) { return Mesh_pool_get(Render_GetMeshPool(), handle); } +void Mesh_DebugPrint(Mesh* mesh) { + printf("Mesh %d vertices %d indices %d joints \n", mesh->geometry.vertices->len, + mesh->geometry.indices->len); +} + size_t ModelExtractRenderEnts(RenderEnt_darray* entities, ModelHandle model_handle, Mat4 affine, RenderEntityFlags flags) { Model* model = MODEL_GET(model_handle); diff --git a/src/render/render.h b/src/render/render.h index 785c140..d752f8b 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -76,6 +76,7 @@ PUB void Mesh_Delete(Mesh* mesh); Mesh* Mesh_Get(MeshHandle handle); void Geometry_Destroy(Geometry* geometry); MeshHandle Mesh_Insert(Mesh* mesh); +void Mesh_DebugPrint(Mesh* mesh); MaterialHandle Material_Insert(Material* material); /** @brief gets render entities from a model and pushes them into a dynamic array for rendering */ diff --git a/src/render/render_types.h b/src/render/render_types.h index 89773a5..5e2b282 100644 --- a/src/render/render_types.h +++ b/src/render/render_types.h @@ -3,6 +3,7 @@ */ #pragma once +#include "animation.h" #include "defines.h" #include "maths_types.h" #include "mem.h" @@ -95,6 +96,9 @@ typedef struct Model { size_t mesh_count; MaterialHandle* materials; size_t material_count; + Armature armature; + bool has_joints; + AnimationClip_darray* animations; } Model; #ifndef TYPED_MODEL_ARRAY KITC_DECL_TYPED_ARRAY(Model) diff --git a/src/render/shadows.c b/src/render/shadows.c index 3d348ea..029eefb 100644 --- a/src/render/shadows.c +++ b/src/render/shadows.c @@ -127,7 +127,7 @@ void Shadow_Init(Shadow_Storage* storage, u32 shadowmap_width, u32 shadowmap_hei storage->debugquad_pipeline = GPU_GraphicsPipeline_Create(debugquad_pipeline_desc, storage->debugquad_pass); - Geometry quad_geo = Geo_CreatePlane(f32x2(1, 1), 1,1 ); + Geometry quad_geo = Geo_CreatePlane(f32x2(1, 1), 1, 1); // HACK: Swap vertices to make it face us Vertex top0 = quad_geo.vertices->data[0]; quad_geo.vertices->data[0] = quad_geo.vertices->data[2]; diff --git a/src/resources/gltf.c b/src/resources/gltf.c index aa4fba5..f788043 100644 --- a/src/resources/gltf.c +++ b/src/resources/gltf.c @@ -34,12 +34,13 @@ 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) -size_t GLTF_LoadMaterials(cgltf_data *data, Str8 relative_path, Material_darray *out_materials); +size_t GLTF_LoadMaterials(cgltf_data* data, Str8 relative_path, Material_darray* out_materials); -ModelHandle ModelLoad_gltf(const char *path, bool invert_texture_y) { +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); @@ -48,10 +49,10 @@ ModelHandle ModelLoad_gltf(const char *path, bool invert_texture_y) { 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); + const char* file_string = string_from_file(path); ModelHandle handle; - Model *model = Model_pool_alloc(&g_core.models, &handle); + Model* model = Model_pool_alloc(&g_core.models, &handle); model->name = Str8_cstr_view(path); bool success = @@ -68,7 +69,7 @@ ModelHandle ModelLoad_gltf(const char *path, bool invert_texture_y) { } void assert_path_type_matches_component_type(cgltf_animation_path_type target_path, - cgltf_accessor *output) { + 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); @@ -77,7 +78,7 @@ void assert_path_type_matches_component_type(cgltf_animation_path_type target_pa // 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) { +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"); @@ -90,7 +91,7 @@ void load_position_components(Vec3_darray *positions, cgltf_accessor *accessor) } } -void load_normal_components(Vec3_darray *normals, cgltf_accessor *accessor) { +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"); @@ -103,7 +104,7 @@ void load_normal_components(Vec3_darray *normals, cgltf_accessor *accessor) { } } -void load_texcoord_components(Vec2_darray *texcoords, cgltf_accessor *accessor) { +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"); @@ -118,7 +119,7 @@ void load_texcoord_components(Vec2_darray *texcoords, cgltf_accessor *accessor) } } -void load_joint_index_components(Vec4u_darray *joint_indices, cgltf_accessor *accessor) { +void load_joint_index_components(Vec4u_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"); @@ -136,26 +137,24 @@ void load_joint_index_components(Vec4u_darray *joint_indices, cgltf_accessor *ac } } -bool model_load_gltf_str(const char *file_string, const char *filepath, Str8 relative_path, - Model *out_model, bool invert_textures_y) { +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); - Vec4u_darray *tmp_joint_indices = Vec4u_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); - u32_darray *tmp_material_indexes = u32_darray_new(1); - Joint_darray *tmp_joints = Joint_darray_new(256); - - // FIXME - // vertex_bone_data_darray *tmp_vertex_bone_data = vertex_bone_data_darray_new(1000); + 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); + u32_darray* tmp_material_indexes = u32_darray_new(1); + + Joint_darray* joints = Joint_darray_new(256); cgltf_options options = { 0 }; - cgltf_data *data = NULL; + cgltf_data* data = NULL; cgltf_result result = cgltf_parse_file(&options, filepath, &data); if (result != cgltf_result_success) { WARN("gltf load failed"); @@ -166,53 +165,63 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, Str8 rel cgltf_load_buffers(&options, data, filepath); DEBUG("loaded buffers"); - // // --- Skin - // size_t num_skins = data->skins_count; - // bool is_skinned = false; - // 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); - - // 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]; - - // joint joint_i = { .name = "testjoint" }; - // 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; - // } 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)); - // } - // // 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); - // } - // } + // --- Skin + size_t num_skins = data->skins_count; + bool is_skinned = false; + 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 = { .arena = arena_create(malloc(MB(1)), MB(1)) }; + printf("Skin %s\n", gltf_skin->name); + armature.label = "test_skin"; + // 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; + + // for each one we'll spit out a joint + for (size_t i = 0; i < num_joints; i++) { + TRACE("Joint %d", i); + cgltf_node* joint_node = gltf_skin->joints[i]; + Joint joint_i = { .debug_label = "test_joint" }; + + 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; + } 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.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(armature.joints, joint_i); + } + + out_model->armature = armature; + out_model->has_joints = true; + } // --- Materials size_t num_materials = GLTF_LoadMaterials(data, relative_path, tmp_materials); @@ -231,33 +240,31 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, Str8 rel 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; + cgltf_accessor* accessor = attribute.data; load_position_components(tmp_positions, accessor); } else if (attribute.type == cgltf_attribute_type_normal) { - cgltf_accessor *accessor = attribute.data; + cgltf_accessor* accessor = attribute.data; load_normal_components(tmp_normals, accessor); } else if (attribute.type == cgltf_attribute_type_texcoord) { - cgltf_accessor *accessor = attribute.data; + 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; + cgltf_accessor* accessor = attribute.data; load_joint_index_components(tmp_joint_indices, accessor); } else if (attribute.type == cgltf_attribute_type_weights) { - // FIXME: weights - // TRACE("Load joint weights from accessor"); - // cgltf_accessor *accessor = attribute.data; - // assert(accessor->component_type == cgltf_component_type_r_32f); - // assert(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); - // } + 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); } @@ -280,28 +287,8 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, Str8 rel TRACE("Vertex data has been loaded"); - // // FIXME - // // 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); - // // } - // // } - - bool has_indices = false; - Vertex_darray *geo_vertices = Vertex_darray_new(3); - u32_darray *geo_indices = u32_darray_new(0); + 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, @@ -311,19 +298,25 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, Str8 rel 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 = { .static_3d = { - .position = tmp_positions->data[v_i], - .normal = has_normals ? tmp_normals->data[v_i] : VEC3_ZERO, - .tex_coords = has_uvs ? tmp_uvs->data[v_i] : vec2_create(0., 0.), - } }; + 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; + cgltf_accessor* indices = primitive.indices; if (primitive.indices > 0) { WARN("indices! %d", indices->count); - has_indices = true; // store indices for (cgltf_size i = 0; i < indices->count; ++i) { @@ -332,169 +325,139 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, Str8 rel u32_darray_push(geo_indices, ei); } - // fetch and store vertices for each index - // for (cgltf_size i = 0; i < indices->count; ++i) { - // Vertex vert; - // cgltf_uint index = mesh.indices[i]; - // vert.position = tmp_positions->data[index]; - // 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 { - // has_indices = false; - // return false; // TODO: handle this - // } - - Geometry *geometry = malloc(sizeof(Geometry)); - geometry->format = VERTEX_STATIC_3D; + 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; + } Mesh_darray_push(tmp_meshes, m); Vec3_darray_clear(tmp_positions); Vec3_darray_clear(tmp_normals); Vec2_darray_clear(tmp_uvs); - Vec4u_darray_clear(tmp_joint_indices); + Vec4i_darray_clear(tmp_joint_indices); Vec4_darray_clear(tmp_weights); + } else { + WARN("No indices found. Ignoring mesh..."); } } - // for (int i = 0; i < out_model->meshes->len; i++) { - // u32 mat_idx = out_model->meshes->data[i].material_index; - // printf("Mesh %d Mat index %d Mat name %s\n", i, mat_idx, - // out_model->materials->data[mat_idx].name); - // } - - // TODO: GLTF_LoadAnimations() - // // 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 * 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 - // out_model->animation_data_arena = - // arena_create(animation_backing_storage, ANIMATION_STORAGE_ARENA_SIZE); - // arena *arena = &out_model->animation_data_arena; - - // 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(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; - // case cgltf_animation_path_type_translation: - // target_property = &clip.translation; - // data_type = KEYFRAME_TRANSLATION; - // break; - // case cgltf_animation_path_type_scale: - // target_property = &clip.scale; - // data_type = KEYFRAME_SCALE; - // break; - // case cgltf_animation_path_type_weights: - // target_property = &clip.weights; - // data_type = KEYFRAME_WEIGHTS; - // WARN("Morph target weights arent supported yet"); - // return false; - // default: - // WARN("unsupported animation type"); - // return false; - // } - // *target_property = sampler; - - // sampler->current_index = 0; - // printf("1 %d index\n", sampler->current_index); - // 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)"); - // 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); - - // assert_path_type_matches_component_type(channel.target_path, - // channel.sampler->output); - - // // keyframe values - // size_t n_values = channel.sampler->output->count; - // assert(n_frames == n_values); - - // keyframes keyframes = { 0 }; - // keyframes.kind = KEYFRAME_ROTATION; - // 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 - // break; - // } - // } - // } - // sampler->animation.values = keyframes; - - // sampler->min = channel.sampler->input->min[0]; - // sampler->max = channel.sampler->input->max[0]; - - // // clip.rotation = sampler; - // // printf("%d timestamps\n", sampler->animation.n_timestamps); - // // printf("%d index\n", sampler->current_index); - // } - - // WARN("stuff %ld", clip.rotation->animation.n_timestamps); - // animation_clip_darray_push(out_model->animations, clip); - // } + // --- 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); + } + arena* arena = &out_model->armature.arena; + + for (int anim_idx = 0; anim_idx < data->animations_count; anim_idx++) { + cgltf_animation animation = data->animations[anim_idx]; + AnimationClip clip = { 0 }; + + // 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 = arena_alloc(arena, sizeof(AnimationSampler)); + + AnimationSampler** target_property; + KeyframeKind data_type; + + switch (channel.target_path) { + case cgltf_animation_path_type_rotation: + target_property = &clip.rotation; + data_type = KEYFRAME_ROTATION; + break; + case cgltf_animation_path_type_translation: + target_property = &clip.translation; + data_type = KEYFRAME_TRANSLATION; + break; + case cgltf_animation_path_type_scale: + target_property = &clip.scale; + data_type = KEYFRAME_SCALE; + break; + case cgltf_animation_path_type_weights: + target_property = &clip.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; + // printf("1 %d index\n", sampler->current_index); + sampler->animation.interpolation = INTERPOLATION_LINEAR; // NOTE: hardcoded for now + + // Keyframe times + size_t n_frames = channel.sampler->input->count; + assert(channel.sampler->input->component_type == cgltf_component_type_r_32f); + 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); + + // assert_path_type_matches_component_type(channel.target_path, + // channel.sampler->output); + + // 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\n", sampler->animation.n_timestamps); + printf("%d index\n", sampler->current_index); + } + + AnimationClip_darray_push(out_model->animations, clip); + } + } } num_meshes = tmp_meshes->len; @@ -505,7 +468,7 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, Str8 rel out_model->materials = malloc(num_materials * sizeof(MaterialHandle)); out_model->material_count = num_materials; - MaterialHandle *mat_handles = calloc(num_materials, sizeof(MaterialHandle)); + 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]); @@ -524,10 +487,10 @@ bool model_load_gltf_str(const char *file_string, const char *filepath, Str8 rel return true; } -const char *bool_yes_no(bool pred) { return pred ? "Yes" : "No"; } +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 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++) { @@ -562,7 +525,6 @@ size_t GLTF_LoadMaterials(cgltf_data *data, Str8 relative_path, Material_darray // -- metallic cgltf_texture_view metal_rough_tex_view = pbr.metallic_roughness_texture; - // bool has_metal_ printf("Metal factor: %f\n", pbr.metallic_factor); printf("Roughness factor: %f\n", pbr.roughness_factor); if (metal_rough_tex_view.texture != NULL) { diff --git a/src/resources/loaders.h b/src/resources/loaders.h index 220a391..ea1f9a2 100644 --- a/src/resources/loaders.h +++ b/src/resources/loaders.h @@ -5,13 +5,13 @@ #include "str.h" // --- Public API -PUB ModelHandle ModelLoad_obj(const char *path, bool invert_texture_y); -PUB ModelHandle ModelLoad_gltf(const char *path, bool invert_texture_y); +PUB ModelHandle ModelLoad_obj(const char* path, bool invert_texture_y); +PUB ModelHandle ModelLoad_gltf(const char* path, bool invert_texture_y); typedef struct GLTF_LoadStats { u32 mesh_count, material_count, vertex_count, index_count, animation_count, joint_count; } GLTF_LoadStats; // --- Internal -bool model_load_gltf_str(const char *file_string, const char *filepath, Str8 relative_path, - Model *out_model, bool invert_textures_y); +bool model_load_gltf_str(const char* file_string, const char* filepath, Str8 relative_path, + Model* out_model, bool invert_textures_y); diff --git a/src/resources/obj.c b/src/resources/obj.c index e02cb9a..a5e9b18 100644 --- a/src/resources/obj.c +++ b/src/resources/obj.c @@ -42,7 +42,7 @@ KITC_DECL_TYPED_ARRAY(face) // bool model_load_obj_str(const char *file_string, str8 relative_path, Model *out_model, // bool invert_textures_y); -ModelHandle model_load_obj(Core *core, const char *path, bool invert_textures_y) { +ModelHandle model_load_obj(Core* core, const char* path, bool invert_textures_y) { size_t arena_size = 1024; arena scratch = arena_create(malloc(arena_size), arena_size); @@ -51,7 +51,7 @@ ModelHandle model_load_obj(Core *core, const char *path, bool invert_textures_y) 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); + const char* file_string = string_from_file(path); ModelHandle handle; // model *model = model_pool_alloc(&g_core.models, &handle); @@ -70,7 +70,7 @@ ModelHandle model_load_obj(Core *core, const char *path, bool invert_textures_y) return handle; } -bool model_load_obj_str(const char *file_string, Str8 relative_path, Model *out_model, +bool model_load_obj_str(const char* file_string, Str8 relative_path, Model* out_model, bool invert_textures_y) { TRACE("Load OBJ from string"); diff --git a/src/std/containers/darray.h b/src/std/containers/darray.h index d8c1e6d..080afb4 100644 --- a/src/std/containers/darray.h +++ b/src/std/containers/darray.h @@ -27,12 +27,12 @@ /* @brief current number of items in the array */ \ size_t len; \ size_t capacity; \ - T *data; \ + T* data; \ } #define typed_array_iterator(T) \ struct { \ - T##_darray *array; \ + T##_darray* array; \ size_t current_idx; \ } @@ -45,9 +45,9 @@ typedef typed_array_iterator(Type) Type##_darray_iter; \ \ /* Create a new one growable array */ \ - PREFIX Type##_darray *Type##_darray_new(size_t starting_capacity) { \ - Type##_darray *d; \ - T *data; \ + PREFIX Type##_darray* Type##_darray_new(size_t starting_capacity) { \ + Type##_darray* d; \ + T* data; \ d = malloc(sizeof(Type##_darray)); \ data = malloc(starting_capacity * sizeof(T)); \ \ @@ -58,16 +58,16 @@ return d; \ } \ \ - PREFIX void Type##_darray_free(Type##_darray *d) { \ + PREFIX void Type##_darray_free(Type##_darray* d) { \ if (d != NULL) { \ free(d->data); \ free(d); \ } \ } \ \ - PREFIX T *Type##_darray_resize(Type##_darray *d, size_t capacity) { \ + PREFIX T* Type##_darray_resize(Type##_darray* d, size_t capacity) { \ /* resize the internal data block */ \ - T *new_data = realloc(d->data, sizeof(T) * capacity); \ + T* new_data = realloc(d->data, sizeof(T) * capacity); \ /* TODO: handle OOM error */ \ \ d->capacity = capacity; \ @@ -75,11 +75,11 @@ return new_data; \ } \ \ - PREFIX void Type##_darray_push(Type##_darray *d, T value) { \ + PREFIX void Type##_darray_push(Type##_darray* d, T value) { \ if (d->len >= d->capacity) { \ size_t new_capacity = \ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \ - T *resized = Type##_darray_resize(d, new_capacity); \ + T* resized = Type##_darray_resize(d, new_capacity); \ (void)resized; \ } \ \ @@ -87,37 +87,37 @@ d->len += 1; \ } \ \ - PREFIX void Type##_darray_push_copy(Type##_darray *d, const T *value) { \ + PREFIX void Type##_darray_push_copy(Type##_darray* d, const T* value) { \ if (d->len >= d->capacity) { \ size_t new_capacity = \ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \ - T *resized = Type##_darray_resize(d, new_capacity); \ + T* resized = Type##_darray_resize(d, new_capacity); \ (void)resized; \ } \ \ - T *place = d->data + d->len; \ + T* place = d->data + d->len; \ d->len += 1; \ memcpy(place, value, sizeof(T)); \ } \ \ - PREFIX void Type##_darray_pop(Type##_darray *d, T *dest) { \ - T *item = d->data + (d->len - 1); \ + PREFIX void Type##_darray_pop(Type##_darray* d, T* dest) { \ + T* item = d->data + (d->len - 1); \ d->len -= 1; \ memcpy(dest, item, sizeof(T)); \ } \ \ - PREFIX void Type##_darray_ins(Type##_darray *d, const T *value, size_t index) { \ + PREFIX void Type##_darray_ins(Type##_darray* d, const T* value, size_t index) { \ /* check if requires resize */ \ if (d->len + 1 > d->capacity) { \ size_t new_capacity = \ d->capacity > 0 ? d->capacity * DARRAY_RESIZE_FACTOR : DARRAY_DEFAULT_CAPACITY; \ - T *resized = Type##_darray_resize(d, new_capacity); \ + T* resized = Type##_darray_resize(d, new_capacity); \ (void)resized; \ } \ \ /* shift existing data after index */ \ - T *insert_dest = d->data + index; \ - T *shift_dest = insert_dest + 1; \ + T* insert_dest = d->data + index; \ + T* shift_dest = insert_dest + 1; \ \ int num_items = d->len - index; \ \ @@ -126,21 +126,21 @@ memcpy(insert_dest, value, sizeof(T)); \ } \ \ - PREFIX void Type##_darray_clear(Type##_darray *d) { \ + PREFIX void Type##_darray_clear(Type##_darray* d) { \ d->len = 0; \ memset(d->data, 0, d->capacity * sizeof(T)); \ } \ \ - PREFIX size_t Type##_darray_len(Type##_darray *d) { return d->len; } \ + PREFIX size_t Type##_darray_len(Type##_darray* d) { return d->len; } \ \ - PREFIX Type##_darray_iter Type##_darray_iter_new(Type##_darray *d) { \ + PREFIX Type##_darray_iter Type##_darray_iter_new(Type##_darray* d) { \ Type##_darray_iter iterator; \ iterator.array = d; \ iterator.current_idx = 0; \ return iterator; \ } \ \ - PREFIX void *Type##_darray_iter_next(Type##_darray_iter *iterator) { \ + PREFIX void* Type##_darray_iter_next(Type##_darray_iter* iterator) { \ if (iterator->current_idx < iterator->array->len) { \ return &iterator->array->data[iterator->current_idx++]; \ } else { \ diff --git a/src/std/str.c b/src/std/str.c index 2aac15f..89c76a0 100644 --- a/src/std/str.c +++ b/src/std/str.c @@ -1,6 +1,7 @@ #include "str.h" #include <assert.h> #include <string.h> +#include "log.h" #include "mem.h" Str8 Str8_create(u8* buf, size_t len) { return (Str8){ .buf = buf, .len = len }; } @@ -33,6 +34,15 @@ char* Str8_to_cstr(arena* a, Str8 s) { return (char*)dest; } +char* Clone_cstr(arena* a, const char* s) { + if (s == NULL) { + WARN("Tried to clone a NULL char*"); + return NULL; + } + Str8 st = Str8_cstr_view(s); + return Str8_to_cstr(a, st); +} + Str8 Str8_concat(arena* a, Str8 left, Str8 right) { size_t n_bytes = left.len + right.len + 1; diff --git a/src/std/str.h b/src/std/str.h index c25c615..a29bf9a 100644 --- a/src/std/str.h +++ b/src/std/str.h @@ -45,6 +45,8 @@ char* Str8_to_cstr(arena* a, Str8 s); @note The backing `string` cannot be modified. */ Str8 Str8_cstr_view(char* string); +char* Clone_cstr(arena* a, const char* s); + // --- Comparisons /** @brief Compare two strings for exact equality */ diff --git a/src/systems/input.c b/src/systems/input.c index 152b349..c3af96a 100644 --- a/src/systems/input.c +++ b/src/systems/input.c @@ -7,9 +7,9 @@ #include "keys.h" #include "log.h" -static Input_State *g_input; // Use a global to simplify caller code +static Input_State* g_input; // Use a global to simplify caller code -bool Input_Init(Input_State *input, GLFWwindow *window) { +bool Input_Init(Input_State* input, GLFWwindow* window) { INFO("Input init"); memset(input, 0, sizeof(Input_State)); @@ -30,9 +30,9 @@ bool Input_Init(Input_State *input, GLFWwindow *window) { return true; } -void Input_Shutdown(Input_State *input) {} +void Input_Shutdown(Input_State* input) {} -void Input_Update(Input_State *input) { +void Input_Update(Input_State* input) { glfwPollEvents(); // --- update keyboard input diff --git a/src/systems/input.h b/src/systems/input.h index 2665a11..c3b2500 100644 --- a/src/systems/input.h +++ b/src/systems/input.h @@ -24,7 +24,7 @@ typedef struct mouse_state { } mouse_state; typedef struct Input_State { - struct GLFWwindow *window; + struct GLFWwindow* window; mouse_state mouse; bool depressed_keys[KEYCODE_MAX]; bool just_pressed_keys[KEYCODE_MAX]; @@ -45,9 +45,9 @@ PUB bool MouseBtn_Held(MouseBtn btn); // --- Lifecycle -PUB bool Input_Init(Input_State *input, struct GLFWwindow *window); -PUB void Input_Shutdown(Input_State *input); +PUB bool Input_Init(Input_State* input, struct GLFWwindow* window); +PUB void Input_Shutdown(Input_State* input); -PUB void Input_Update(Input_State *state); // must be run once per main loop +PUB void Input_Update(Input_State* state); // must be run once per main loop PUB mouse_state Input_GetMouseState();
\ No newline at end of file |