From c736ebd01349fa95a2aa54ecb9ab2df90cc031c0 Mon Sep 17 00:00:00 2001 From: Cameron Reikes Date: Thu, 6 Jul 2023 22:19:21 -0700 Subject: [PATCH] Armatures can have custom images, support non-alpha images in load image --- art/Exporter.py | 7 +++-- art/art.blend | 4 +-- main.c | 73 +++++++++++++++++++++++++++++++++++-------------- tuning.h | 4 +-- 4 files changed, 61 insertions(+), 27 deletions(-) diff --git a/art/Exporter.py b/art/Exporter.py index a34f6c5..8ac656a 100644 --- a/art/Exporter.py +++ b/art/Exporter.py @@ -117,12 +117,15 @@ for o in D.objects: if o.users_collection[0].name == 'Level': assert False, "Cannot put armatures in the level. The level is for static placed meshes. For dynamic entities, you put them outside of the level collection, their entity kind is encoded, and the game code decides how to draw them" else: - placed_entities.append((mesh_object.name,) + object_transform_info) + pass + #placed_entities.append((mesh_object.name,) + object_transform_info) armature_name = o.data.name output_filepath = bpy.path.abspath(f"//{EXPORT_DIRECTORY}/{armature_name}.bin") - print(f"Exporting armature to {output_filepath}") + image_filename = ensure_tex_saved_and_get_name(mesh_object) + print(f"Exporting armature with image filename {image_filename} to {output_filepath}") with open(output_filepath, "wb") as f: write_b8(f, True) + write_string(f, image_filename) bones_in_armature = [] for b in o.data.bones: bones_in_armature.append(b) diff --git a/art/art.blend b/art/art.blend index 33f8bd8..4336ed5 100644 --- a/art/art.blend +++ b/art/art.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:095df908c36e489ea27ea075003f5e5b8fc559b7481156fc62e5b52973d6488d -size 17659396 +oid sha256:d626e77a84d48fd912dc6f80459e87148b4803ed5da98084531a05d90035a917 +size 13614884 diff --git a/main.c b/main.c index 69f97ce..b87f767 100644 --- a/main.c +++ b/main.c @@ -761,6 +761,7 @@ LoadedImage *loaded_images = 0; sg_image load_image(MD_String8 path) { + MD_ArenaTemp scratch = MD_GetScratch(0, 0); for(LoadedImage *cur = loaded_images; cur; cur = cur->next) { if(MD_S8Match(cur->name, path, 0)) @@ -781,7 +782,26 @@ sg_image load_image(MD_String8 path) (const char*)nullterm(frame_arena, path).str, &png_width, &png_height, &num_channels, 0); + + bool free_the_pixels = true; + if(num_channels == 3) + { + stbi_uc *old_pixels = pixels; + pixels = MD_ArenaPush(scratch.arena, png_width * png_height * 4 * sizeof(stbi_uc)); + for(MD_u64 pixel_i = 0; pixel_i < png_width * png_height; pixel_i++) + { + pixels[pixel_i*4 + 0] = old_pixels[pixel_i*3 + 0]; + pixels[pixel_i*4 + 1] = old_pixels[pixel_i*3 + 1]; + pixels[pixel_i*4 + 2] = old_pixels[pixel_i*3 + 2]; + pixels[pixel_i*4 + 3] = 255; + } + num_channels = 4; + free_the_pixels = false; + stbi_image_free(old_pixels); + } + assert(pixels); + assert(desired_channels == num_channels); Log("Path %.*s | Loading image with dimensions %d %d\n", MD_S8VArg(path), png_width, png_height); to_return = sg_make_image(&(sg_image_desc) { @@ -796,11 +816,11 @@ sg_image load_image(MD_String8 path) .data.subimage[0][0] = { .ptr = pixels, - .size = (size_t)(png_width * png_height * 4), + .size = (size_t)(png_width * png_height * num_channels), } }); - stbi_image_free(pixels); loaded->image = to_return; + MD_ReleaseScratch(scratch); return to_return; } @@ -861,7 +881,7 @@ typedef struct Mesh MD_u64 num_vertices; sg_buffer loaded_buffer; - sg_image mesh_image; + sg_image image; MD_String8 name; } Mesh; @@ -927,7 +947,7 @@ Mesh load_mesh(MD_Arena *arena, MD_String8 binary_file, MD_String8 mesh_name) .error_arena = scratch.arena, .serializing = false, }; - Mesh out = {0}; + Mesh to_return = {0}; bool is_armature; ser_bool(&ser, &is_armature); @@ -935,31 +955,31 @@ Mesh load_mesh(MD_Arena *arena, MD_String8 binary_file, MD_String8 mesh_name) MD_String8 image_filename; ser_MD_String8(&ser, &image_filename, scratch.arena); - out.mesh_image = load_image(MD_S8Fmt(scratch.arena, "assets/exported_3d/%.*s", MD_S8VArg(image_filename))); + to_return.image = load_image(MD_S8Fmt(scratch.arena, "assets/exported_3d/%.*s", MD_S8VArg(image_filename))); - ser_MD_u64(&ser, &out.num_vertices); - Log("Mesh %.*s has %llu vertices and image filename '%.*s'\n", MD_S8VArg(mesh_name), out.num_vertices, MD_S8VArg(image_filename)); + ser_MD_u64(&ser, &to_return.num_vertices); + Log("Mesh %.*s has %llu vertices and image filename '%.*s'\n", MD_S8VArg(mesh_name), to_return.num_vertices, MD_S8VArg(image_filename)); - out.vertices = MD_ArenaPush(arena, sizeof(*out.vertices) * out.num_vertices); - for(MD_u64 i = 0; i < out.num_vertices; i++) + to_return.vertices = MD_ArenaPush(arena, sizeof(*to_return.vertices) * to_return.num_vertices); + for(MD_u64 i = 0; i < to_return.num_vertices; i++) { - ser_Vertex(&ser, &out.vertices[i]); + ser_Vertex(&ser, &to_return.vertices[i]); } assert(!ser.cur_error.failed); MD_ReleaseScratch(scratch); - out.loaded_buffer = sg_make_buffer(&(sg_buffer_desc) + to_return.loaded_buffer = sg_make_buffer(&(sg_buffer_desc) { .usage = SG_USAGE_IMMUTABLE, - .data = (sg_range){.ptr = out.vertices, .size = out.num_vertices * sizeof(Vertex)}, + .data = (sg_range){.ptr = to_return.vertices, .size = to_return.num_vertices * sizeof(Vertex)}, .label = (const char*)nullterm(arena, MD_S8Fmt(arena, "%.*s-vertices", MD_S8VArg(mesh_name))).str, }); - out.name = mesh_name; + to_return.name = mesh_name; - return out; + return to_return; } // stored in row major @@ -1029,6 +1049,7 @@ typedef struct sg_buffer loaded_buffer; sg_image bones_texture; + sg_image image; int bones_texture_width; int bones_texture_height; } Armature; @@ -1048,7 +1069,12 @@ Armature load_armature(MD_Arena *arena, MD_String8 binary_file, MD_String8 armat bool is_armature; ser_bool(&ser, &is_armature); assert(is_armature); - + + MD_String8 image_filename; + ser_MD_String8(&ser, &image_filename, scratch.arena); + arena->align = 16; // SSE requires quaternions are 16 byte aligned + to_return.image = load_image(MD_S8Fmt(scratch.arena, "assets/exported_3d/%.*s", MD_S8VArg(image_filename))); + ser_MD_u64(&ser, &to_return.bones_length); Log("Armature %.*s has %llu bones\n", MD_S8VArg(armature_name), to_return.bones_length); to_return.bones = MD_PushArray(arena, Bone, to_return.bones_length); @@ -2794,7 +2820,7 @@ void draw_placed(Mat4 view, Mat4 projection, Mat4 light_matrix, PlacedMesh *cur) { *it = (sg_image){0}; } - state.threedee_bind.fs_images[SLOT_threedee_tex] = drawing->mesh_image; + state.threedee_bind.fs_images[SLOT_threedee_tex] = drawing->image; state.threedee_bind.fs_images[SLOT_threedee_shadow_map] = state.shadows.color_img; state.threedee_bind.vertex_buffers[0] = drawing->loaded_buffer; sg_apply_bindings(&state.threedee_bind); @@ -3178,8 +3204,8 @@ void init(void) mesh_player = load_mesh(persistent_arena, binary_file, MD_S8Lit("Player.bin")); - binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/WalkingArmature.bin")); - armature = load_armature(persistent_arena, binary_file, MD_S8Lit("WalkingArmature.bin")); + binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/ArmatureExportedWithAnims.bin")); + armature = load_armature(persistent_arena, binary_file, MD_S8Lit("ArmatureExportedWithAnims.bin")); @@ -4126,7 +4152,7 @@ void draw_armature(Mat4 view, Mat4 projection, Transform t, Armature *armature) state.threedee_bind.vertex_buffers[0] = armature->loaded_buffer; state.threedee_bind.vs_images[SLOT_armature_bones_tex] = armature->bones_texture; - state.threedee_bind.fs_images[SLOT_armature_tex] = image_gigatexture; + state.threedee_bind.fs_images[SLOT_armature_tex] = armature->image; sg_apply_bindings(&state.threedee_bind); @@ -5245,7 +5271,7 @@ void frame(void) Vec3 player_pos = V3(gs.player->pos.x, 0.0, gs.player->pos.y); //dbgline(V2(0,0), V2(500, 500)); const float vertical_to_horizontal_ratio = 0.8f; - const float cam_distance = 20.0f; + const float cam_distance = 35.0f; Vec3 away_from_player; { float ratio = vertical_to_horizontal_ratio; @@ -5355,6 +5381,7 @@ void frame(void) state.threedee_bind.fs_images[SLOT_threedee_tex] = image_gigatexture; state.threedee_bind.fs_images[SLOT_threedee_shadow_map] = state.shadows.color_img; + view = Translate(V3(0.0, 1.0, -5.0f)); //view = LookAt_RH(V3(0,1,-5 if(flycam) @@ -6407,7 +6434,7 @@ void frame(void) if(gs.player->state == CHARACTER_WALKING) { - armature.go_to_animation = MD_S8Lit("Walking"); + armature.go_to_animation = MD_S8Lit("Running"); } else { @@ -7005,6 +7032,9 @@ void frame(void) if (show_devtools) PROFILE_SCOPE("statistics") { + // shadow map + draw_quad((DrawParams){quad_at(V2(screen_size().x - 512.0f, screen_size().y), V2(512.0f, 512.0f)), IMG(state.shadows.color_img), WHITE, .layer = LAYER_UI_FG}); + Vec2 pos = V2(0.0, screen_size().Y); int num_entities = 0; ENTITIES_ITER(gs.entities) num_entities++; @@ -7440,6 +7470,7 @@ sapp_desc sokol_main(int argc, char* argv[]) .frame_cb = frame, .cleanup_cb = cleanup, .event_cb = event, + .sample_count = 4, .width = 800, .height = 600, //.gl_force_gles2 = true, not sure why this was here in example, look into diff --git a/tuning.h b/tuning.h index 395292b..d81ca44 100644 --- a/tuning.h +++ b/tuning.h @@ -3,7 +3,7 @@ #define LEVEL_TILES 150 // width and height of level tiles array #define LAYERS 3 #define TILE_SIZE 0.5f // in pixels -#define PLAYER_SPEED 0.2f // in meters per second +#define PLAYER_SPEED 0.5f // in meters per second #define PLAYER_ROLL_SPEED 7.0f #define PERCEPTION_HEARING_RAGE (TILE_SIZE*4.0f) #define CHARACTERS_PER_SEC 45.0f @@ -35,7 +35,7 @@ #define SENTENCE_CONST(txt) { .data = txt, .cur_index = sizeof(txt) } #define SENTENCE_CONST_CAST(txt) (Sentence)SENTENCE_CONST(txt) -#define ANIMATION_BLEND_TIME 0.3f +#define ANIMATION_BLEND_TIME 0.15f #define REMEMBERED_MEMORIES 32 #define REMEMBERED_ERRORS 6