Skin mesh vertices from bone pose in vert shader, fix rotation of

objects being weird
main
parent cbce6c9a81
commit 6ce37294be

@ -0,0 +1,59 @@
@module armature
@vs vs
in vec3 pos_in;
in vec2 uv_in;
in vec4 indices_in; // is a sokol SG_VERTEXFORMAT_USHORT4N, a 16 bit unsigned integer treated as a floating point number due to webgl compatibility
in vec4 weights_in;
out vec3 pos;
out vec2 uv;
uniform vs_params {
mat4 model;
mat4 view;
mat4 projection;
mat4 bones[4];
};
void main() {
vec4 total_position = vec4(0.0f);
for(int i = 0; i < 4; i++)
{
float index_float = indices_in[i];
int index = int(index_float * 65535.0);
float weight = weights_in[i];
vec4 local_position = bones[index] * vec4(pos_in, 1.0f);
total_position += local_position * weight;
}
gl_Position = projection * view * model * total_position;
//gl_Position = projection * view * model * vec4(pos_in, 1.0);
pos = gl_Position.xyz;
uv = uv_in;
}
@end
@fs fs
uniform sampler2D tex;
in vec3 pos;
in vec2 uv;
out vec4 frag_color;
void main() {
vec4 col = texture(tex, uv);
if(col.a < 0.5)
{
discard;
}
else
{
frag_color = vec4(col.rgb, 1.0);
}
}
@end
@program program vs fs

@ -30,6 +30,9 @@ def write_u64(f, number: int):
def write_i32(f, number: int): def write_i32(f, number: int):
f.write(bytes(struct.pack("i", number))) f.write(bytes(struct.pack("i", number)))
def write_u16(f, number: int): # unsigned short, used in shaders to figure out which bone index is current
f.write(bytes(struct.pack("H", number)))
def write_v3(f, vector): def write_v3(f, vector):
write_f32(f, vector.x) write_f32(f, vector.x)
write_f32(f, vector.y) write_f32(f, vector.y)
@ -52,6 +55,13 @@ def write_4x4matrix(f, m):
for col in range(4): for col in range(4):
write_f32(f, m[row][col]) write_f32(f, m[row][col])
def normalize_joint_weights(weights):
total_weights = sum(weights)
result = [0,0,0,0]
if total_weights != 0:
for i, weight in enumerate(weights): result[i] = weight/total_weights
return result
# for the level.bin # for the level.bin
level_object_data = [] level_object_data = []
collision_cubes = [] collision_cubes = []
@ -66,6 +76,10 @@ mapping = axis_conversion(
) )
mapping.resize_4x4() mapping.resize_4x4()
with open(bpy.path.abspath(f"//{EXPORT_DIRECTORY}/shorttest.bin"), "wb") as f:
for i in range(4):
write_u16(f, i)
# meshes can either be Meshes, or Armatures. Armatures contain all mesh data to draw it, and any anims it has # meshes can either be Meshes, or Armatures. Armatures contain all mesh data to draw it, and any anims it has
for o in D.objects: for o in D.objects:
@ -73,9 +87,9 @@ for o in D.objects:
if o.parent and o.parent.type == "ARMATURE": if o.parent and o.parent.type == "ARMATURE":
mesh_object = o mesh_object = o
o = o.parent o = o.parent
object_transform_info = (mesh_name, mapping @ mesh_object.location, mesh_object.rotation_euler, mesh_object.scale) object_transform_info = (mesh_name, mapping @ o.location, o.rotation_euler, o.scale)
if o.users_collection[0].name == 'Level': 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") 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: else:
placed_entities.append((mesh_object.name,) + object_transform_info) placed_entities.append((mesh_object.name,) + object_transform_info)
armature_name = o.data.name armature_name = o.data.name
@ -115,6 +129,7 @@ for o in D.objects:
parent_space_pose = pose_bone.parent.matrix.inverted() @ pose_bone.matrix parent_space_pose = pose_bone.parent.matrix.inverted() @ pose_bone.matrix
else: else:
parent_space_pose = mapping @ pose_bone.matrix parent_space_pose = mapping @ pose_bone.matrix
#parent_space_pose = pose_bone.matrix
print("parent_space_pose of the bone with no parent:") print("parent_space_pose of the bone with no parent:")
print(parent_space_pose) print(parent_space_pose)
@ -138,7 +153,7 @@ for o in D.objects:
vertices = [] vertices = []
armature = o
for polygon in mesh.polygons: for polygon in mesh.polygons:
if len(polygon.loop_indices) == 3: if len(polygon.loop_indices) == 3:
for loopIndex in polygon.loop_indices: for loopIndex in polygon.loop_indices:
@ -147,16 +162,38 @@ for o in D.objects:
uv = mesh.uv_layers.active.data[loop.index].uv uv = mesh.uv_layers.active.data[loop.index].uv
normal = loop.normal normal = loop.normal
vertices.append((position, uv)) jointIndices = [0,0,0,0]
jointWeights = [0,0,0,0]
for jointBindingIndex, group in enumerate(mesh.vertices[loop.vertex_index].groups):
if jointBindingIndex < 4:
groupIndex = group.group
boneName = mesh_object.vertex_groups[groupIndex].name
jointIndices[jointBindingIndex] = armature.data.bones.find(boneName)
if jointIndices[jointBindingIndex] == -1:
# it's fine that this references a real bone, the bone at index 0,
# because the weight of its influence is 0
jointIndices[jointBindingIndex] = 0
jointWeights[jointBindingIndex] = 0.0
else:
jointWeights[jointBindingIndex] = group.weight
vertices.append((position, uv, jointIndices, normalize_joint_weights(jointWeights)))
write_u64(f, len(vertices)) write_u64(f, len(vertices))
vertex_i = 0
for v_and_uv in vertices: for v_and_uv in vertices:
v, uv = v_and_uv v, uv, jointIndices, jointWeights = v_and_uv
write_f32(f, v.x) write_f32(f, v.x)
write_f32(f, v.y) write_f32(f, v.y)
write_f32(f, v.z) write_f32(f, v.z)
write_f32(f, uv.x) write_f32(f, uv.x)
write_f32(f, uv.y) write_f32(f, uv.y)
for i in range(4):
write_u16(f, jointIndices[i])
for i in range(4):
write_f32(f, jointWeights[i])
vertex_i += 1
print(f"Wrote {len(vertices)} vertices") print(f"Wrote {len(vertices)} vertices")
else: # if the parent type isn't an armature, i.e just a bog standard mesh else: # if the parent type isn't an armature, i.e just a bog standard mesh

BIN
art/art.blend (Stored with Git LFS)

Binary file not shown.

126
main.c

@ -187,6 +187,7 @@ int min(int a, int b)
// so can be grep'd and removed // so can be grep'd and removed
#define dbgprint(...) { printf("Debug | %s:%d | ", __FILE__, __LINE__); printf(__VA_ARGS__); } #define dbgprint(...) { printf("Debug | %s:%d | ", __FILE__, __LINE__); printf(__VA_ARGS__); }
#define v3varg(v) v.x, v.y, v.z #define v3varg(v) v.x, v.y, v.z
#define v2varg(v) v.x, v.y
#define qvarg(v) v.x, v.y, v.z, v.w #define qvarg(v) v.x, v.y, v.z, v.w
Vec2 RotateV2(Vec2 v, float theta) Vec2 RotateV2(Vec2 v, float theta)
{ {
@ -795,6 +796,7 @@ SER_MAKE_FOR_TYPE(Vec3);
SER_MAKE_FOR_TYPE(AnimKind); SER_MAKE_FOR_TYPE(AnimKind);
SER_MAKE_FOR_TYPE(EntityRef); SER_MAKE_FOR_TYPE(EntityRef);
SER_MAKE_FOR_TYPE(NPCPlayerStanding); SER_MAKE_FOR_TYPE(NPCPlayerStanding);
SER_MAKE_FOR_TYPE(MD_u16);
void ser_Quat(SerState *ser, Quat *q) void ser_Quat(SerState *ser, Quat *q)
{ {
@ -816,6 +818,8 @@ typedef struct
{ {
Vec3 position; Vec3 position;
Vec2 uv; Vec2 uv;
MD_u16 joint_indices[4];
float joint_weights[4];
} ArmatureVertex; } ArmatureVertex;
SER_MAKE_FOR_TYPE(Vertex); SER_MAKE_FOR_TYPE(Vertex);
@ -1037,6 +1041,17 @@ Armature load_armature(MD_Arena *arena, MD_String8 binary_file, MD_String8 armat
{ {
ser_Vec3(&ser, &to_return.vertices[i].position); ser_Vec3(&ser, &to_return.vertices[i].position);
ser_Vec2(&ser, &to_return.vertices[i].uv); ser_Vec2(&ser, &to_return.vertices[i].uv);
MD_u16 joint_indices[4];
float joint_weights[4];
for(int ii = 0; ii < 4; ii++)
ser_MD_u16(&ser, &joint_indices[ii]);
for(int ii = 0; ii < 4; ii++)
ser_float(&ser, &joint_weights[ii]);
for(int ii = 0; ii < 4; ii++)
to_return.vertices[i].joint_indices[ii] = joint_indices[ii];
for(int ii = 0; ii < 4; ii++)
to_return.vertices[i].joint_weights[ii] = joint_weights[ii];
} }
Log("Armature %.*s has %llu vertices\n", MD_S8VArg(armature_name), to_return.vertices_length); Log("Armature %.*s has %llu vertices\n", MD_S8VArg(armature_name), to_return.vertices_length);
@ -1163,7 +1178,7 @@ ThreeDeeLevel load_level(MD_Arena *arena, MD_String8 binary_file)
if(!mesh_found) if(!mesh_found)
{ {
MD_String8 to_load_filepath = MD_S8Fmt(scratch.arena, "assets/exported_3d/%.*s.bin", MD_S8VArg(placed_mesh_name)); MD_String8 to_load_filepath = MD_S8Fmt(scratch.arena, "assets/exported_3d/%.*s.bin", MD_S8VArg(placed_mesh_name));
Log("Loading '%.*s'...\n", MD_S8VArg(to_load_filepath)); Log("Loading mesh '%.*s'...\n", MD_S8VArg(to_load_filepath));
MD_String8 binary_mesh_file = MD_LoadEntireFile(scratch.arena, to_load_filepath); MD_String8 binary_mesh_file = MD_LoadEntireFile(scratch.arena, to_load_filepath);
if(!binary_mesh_file.str) if(!binary_mesh_file.str)
{ {
@ -1204,6 +1219,7 @@ ThreeDeeLevel load_level(MD_Arena *arena, MD_String8 binary_file)
MD_String8 placed_entity_name = {0}; MD_String8 placed_entity_name = {0};
ser_MD_String8(&ser, &placed_entity_name, scratch.arena); ser_MD_String8(&ser, &placed_entity_name, scratch.arena);
bool found = false; bool found = false;
ARR_ITER_I(CharacterGen, characters, kind) ARR_ITER_I(CharacterGen, characters, kind)
{ {
@ -1224,6 +1240,8 @@ ThreeDeeLevel load_level(MD_Arena *arena, MD_String8 binary_file)
{ {
ser.cur_error = (SerError){.failed = true, .why = MD_S8Fmt(arena, "Couldn't find placed npc kind '%.*s'...\n", MD_S8VArg(placed_entity_name))}; ser.cur_error = (SerError){.failed = true, .why = MD_S8Fmt(arena, "Couldn't find placed npc kind '%.*s'...\n", MD_S8VArg(placed_entity_name))};
} }
Log("Loaded placed entity '%.*s' at %f %f %f\n", MD_S8VArg(placed_entity_name), v3varg(new_placed->t.offset));
} }
} }
@ -1237,6 +1255,7 @@ ThreeDeeLevel load_level(MD_Arena *arena, MD_String8 binary_file)
#include "assets.gen.c" #include "assets.gen.c"
#include "quad-sapp.glsl.h" #include "quad-sapp.glsl.h"
#include "threedee.glsl.h" #include "threedee.glsl.h"
#include "armature.glsl.h"
AABB level_aabb = { .upper_left = { 0.0f, 0.0f }, .lower_right = { TILE_SIZE * LEVEL_TILES, -(TILE_SIZE * LEVEL_TILES) } }; AABB level_aabb = { .upper_left = { 0.0f, 0.0f }, .lower_right = { TILE_SIZE * LEVEL_TILES, -(TILE_SIZE * LEVEL_TILES) } };
GameState gs = { 0 }; GameState gs = { 0 };
@ -2599,6 +2618,7 @@ static struct
sg_bindings bind; sg_bindings bind;
sg_pipeline threedee_pip; sg_pipeline threedee_pip;
sg_pipeline armature_pip;
sg_bindings threedee_bind; sg_bindings threedee_bind;
} state; } state;
@ -2610,6 +2630,7 @@ void draw_placed(Mat4 view, Mat4 projection, PlacedMesh *cur)
{ {
Mesh *drawing = cur->draw_with; Mesh *drawing = cur->draw_with;
state.threedee_bind.vertex_buffers[0] = drawing->loaded_buffer; state.threedee_bind.vertex_buffers[0] = drawing->loaded_buffer;
sg_apply_pipeline(state.threedee_pip);
sg_apply_bindings(&state.threedee_bind); sg_apply_bindings(&state.threedee_bind);
Mat4 model = transform_to_mat(cur->t); Mat4 model = transform_to_mat(cur->t);
@ -2628,16 +2649,32 @@ void draw_placed(Mat4 view, Mat4 projection, PlacedMesh *cur)
void draw_armature(Mat4 view, Mat4 projection, Transform t, Armature *armature) void draw_armature(Mat4 view, Mat4 projection, Transform t, Armature *armature)
{ {
state.threedee_bind.vertex_buffers[0] = armature->loaded_buffer; state.threedee_bind.vertex_buffers[0] = armature->loaded_buffer;
sg_apply_pipeline(state.armature_pip);
sg_apply_bindings(&state.threedee_bind); sg_apply_bindings(&state.threedee_bind);
Mat4 model = transform_to_mat(t); Mat4 model = transform_to_mat(t);
threedee_vs_params_t params = {0}; armature_vs_params_t params = {0};
memcpy(params.model, (float*)&model, sizeof(model)); memcpy(params.model, (float*)&model, sizeof(model));
memcpy(params.view, (float*)&view, sizeof(view)); memcpy(params.view, (float*)&view, sizeof(view));
memcpy(params.projection, (float*)&projection, sizeof(projection)); memcpy(params.projection, (float*)&projection, sizeof(projection));
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_threedee_vs_params, &SG_RANGE(params)); for(MD_u64 i = 0; i < armature->bones_length; i++)
{
Bone *cur = &armature->bones[i];
PoseBone *cur_pose_bone = &armature->poses[i];
Mat4 final = M4D(1.0f);
final = MulM4(cur->inverse_model_space_pos, final);
for(PoseBone *cur_posebone = cur_pose_bone; cur_posebone; cur_posebone = cur_posebone->parent)
{
final = MulM4(cur_posebone->parent_space_pose, final);
}
memcpy(params.bones[i], (float*)&final, sizeof(final));
}
sg_apply_uniforms(SG_SHADERSTAGE_VS, SLOT_armature_vs_params, &SG_RANGE(params));
num_draw_calls += 1; num_draw_calls += 1;
num_vertices += (int)armature->vertices_length; num_vertices += (int)armature->vertices_length;
sg_draw(0, (int)armature->vertices_length, 1); sg_draw(0, (int)armature->vertices_length, 1);
@ -2871,8 +2908,13 @@ void init(void)
DialogNode cur_node = { 0 }; DialogNode cur_node = { 0 };
load_assets(); load_assets();
MD_String8 binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/Player.bin")); MD_String8 binary_file;
binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/level.bin"));
level_threedee = load_level(persistent_arena, binary_file);
binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/Player.bin"));
mesh_player = load_mesh(persistent_arena, binary_file, MD_S8Lit("Player.bin")); mesh_player = load_mesh(persistent_arena, binary_file, MD_S8Lit("Player.bin"));
@ -2883,8 +2925,6 @@ void init(void)
MD_ArenaClear(frame_arena); MD_ArenaClear(frame_arena);
binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/level.bin"));
level_threedee = load_level(persistent_arena, binary_file);
reset_level(); reset_level();
#ifdef DEVTOOLS #ifdef DEVTOOLS
@ -3029,6 +3069,40 @@ void init(void)
.label = "threedee", .label = "threedee",
}); });
desc = armature_program_shader_desc(sg_query_backend());
assert(desc);
shd = sg_make_shader(desc);
state.armature_pip = sg_make_pipeline(&(sg_pipeline_desc)
{
.shader = shd,
.depth = {
.compare = SG_COMPAREFUNC_LESS_EQUAL,
.write_enabled = true
},
.layout = {
.attrs =
{
[ATTR_armature_vs_pos_in].format = SG_VERTEXFORMAT_FLOAT3,
[ATTR_armature_vs_uv_in].format = SG_VERTEXFORMAT_FLOAT2,
[ATTR_armature_vs_indices_in].format = SG_VERTEXFORMAT_USHORT4N,
[ATTR_armature_vs_weights_in].format = SG_VERTEXFORMAT_FLOAT4,
}
},
.colors[0].blend = (sg_blend_state) { // allow transparency
.enabled = true,
.src_factor_rgb = SG_BLENDFACTOR_SRC_ALPHA,
.dst_factor_rgb = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
.op_rgb = SG_BLENDOP_ADD,
.src_factor_alpha = SG_BLENDFACTOR_ONE,
.dst_factor_alpha = SG_BLENDFACTOR_ONE_MINUS_SRC_ALPHA,
.op_alpha = SG_BLENDOP_ADD,
},
.label = "armature",
});
state.clear_depth_buffer_pass_action = (sg_pass_action) state.clear_depth_buffer_pass_action = (sg_pass_action)
{ {
.colors[0] = { .action = SG_ACTION_LOAD }, .colors[0] = { .action = SG_ACTION_LOAD },
@ -3942,7 +4016,6 @@ Vec2 move_and_slide(MoveSlideParams p)
BUFF_ITER(CollisionObj, &to_check) BUFF_ITER(CollisionObj, &to_check)
{ {
dbgplanerect(it->aabb);
if (overlapping(at_new, it->aabb)) if (overlapping(at_new, it->aabb))
{ {
BUFF_APPEND(&actually_overlapping, *it); BUFF_APPEND(&actually_overlapping, *it);
@ -4521,10 +4594,11 @@ void draw_item(ItemKind kind, AABB in_aabb, float alpha)
Transform entity_transform(Entity *e) Transform entity_transform(Entity *e)
{ {
// the mods to e->rotation here are just chosen based on what looks right with model // Models must face +X in blender. This is because, in the 2d game coordinate system,
// facing forward towards // a zero degree 2d rotation means you're facing +x, and this is how it is in the game logic.
Quat entity_rot = QFromAxisAngle_RH(V3(0,1,0), AngleRad(-e->rotation - PI32/2.0f)); // The rotation is negative for some reason that I'm not quite sure about though, something about
//dbgplaneline(e->pos, AddV2(e->pos, RotateV2(V2(5.0f, 0.0), e->rotation))); // the handedness of the 3d coordinate system not matching the handedness of the 2d coordinate system
Quat entity_rot = QFromAxisAngle_RH(V3(0,1,0), AngleRad(-e->rotation));
return (Transform){.offset = AddV3(plane_point(e->pos), V3(0,0,0)), .rotation = entity_rot, .scale = V3(1, 1, 1)}; return (Transform){.offset = AddV3(plane_point(e->pos), V3(0,0,0)), .rotation = entity_rot, .scale = V3(1, 1, 1)};
/* /*
@ -4574,7 +4648,6 @@ void frame(void)
uint64_t time_start_frame = stm_now(); uint64_t time_start_frame = stm_now();
Vec3 player_pos = V3(gs.player->pos.x, 0.0, gs.player->pos.y); Vec3 player_pos = V3(gs.player->pos.x, 0.0, gs.player->pos.y);
dbg3dline(player_pos, V3(0,0,0));
//dbgline(V2(0,0), V2(500, 500)); //dbgline(V2(0,0), V2(500, 500));
const float vertical_to_horizontal_ratio = 0.8f; const float vertical_to_horizontal_ratio = 0.8f;
const float cam_distance = 20.0f; const float cam_distance = 20.0f;
@ -4638,6 +4711,7 @@ void frame(void)
} }
projection = Perspective_RH_NO(PI32/4.0f, screen_size().x / screen_size().y, 0.01f, 1000.0f); projection = Perspective_RH_NO(PI32/4.0f, screen_size().x / screen_size().y, 0.01f, 1000.0f);
// debug draw armature
assert(armature.bones_length == armature.poses_length); assert(armature.bones_length == armature.poses_length);
for(MD_u64 i = 0; i < armature.bones_length; i++) for(MD_u64 i = 0; i < armature.bones_length; i++)
{ {
@ -4650,6 +4724,7 @@ void frame(void)
Vec3 x = MulM4V3(cur->matrix_local, V3(cur->length,0,0)); Vec3 x = MulM4V3(cur->matrix_local, V3(cur->length,0,0));
Vec3 y = MulM4V3(cur->matrix_local, V3(0,cur->length,0)); Vec3 y = MulM4V3(cur->matrix_local, V3(0,cur->length,0));
Vec3 z = MulM4V3(cur->matrix_local, V3(0,0,cur->length)); Vec3 z = MulM4V3(cur->matrix_local, V3(0,0,cur->length));
Vec3 dot = MulM4V3(cur->matrix_local, V3(cur->length,0,cur->length));
Vec3 should_be_zero = MulM4V3(cur->inverse_model_space_pos, from); Vec3 should_be_zero = MulM4V3(cur->inverse_model_space_pos, from);
assert(should_be_zero.x == 0.0); assert(should_be_zero.x == 0.0);
@ -4660,9 +4735,16 @@ void frame(void)
{ {
// do some testing on the bone with no parent // do some testing on the bone with no parent
Vec3 should_be_zero = MulM4V3(cur_pose_bone->parent_space_pose, V3(0,0,0)); Vec3 should_be_zero = MulM4V3(cur_pose_bone->parent_space_pose, V3(0,0,0));
assert(should_be_zero.x == 0.0);
// there is another bone, that's not at (0,0,0) in model space on the model
// for debugging purposes right now
assert(should_be_zero.y == 0.0); assert(should_be_zero.y == 0.0);
/*
assert(should_be_zero.x == 0.0);
assert(should_be_zero.z == 0.0); assert(should_be_zero.z == 0.0);
*/
} }
// from, x, y, and z are like vertex points. They are model-space // from, x, y, and z are like vertex points. They are model-space
@ -4677,25 +4759,35 @@ void frame(void)
final_mat = MulM4(cur->parent_space_pose, final_mat); final_mat = MulM4(cur->parent_space_pose, final_mat);
} }
// uncommenting this skips the pose transform, showing the debug skeleton
// as if it were in "edit mode" in blender
//final_mat = M4D(1.0f);
from = MulM4V3(final_mat, from); from = MulM4V3(final_mat, from);
x = MulM4V3(final_mat, x); x = MulM4V3(final_mat, x);
y = MulM4V3(final_mat, y); y = MulM4V3(final_mat, y);
z = MulM4V3(final_mat, z); z = MulM4V3(final_mat, z);
dot = MulM4V3(final_mat, dot);
from = AddV3(from, offset); from = AddV3(from, offset);
x = AddV3(x, offset); x = AddV3(x, offset);
y = AddV3(y, offset); y = AddV3(y, offset);
z = AddV3(z, offset); z = AddV3(z, offset);
dot = AddV3(dot, offset);
dbgcol(LIGHTBLUE) dbgcol(LIGHTBLUE)
dbgsquare3d(y); dbgsquare3d(y);
dbgcol(RED) dbgcol(RED)
dbg3dline(from, x); dbg3dline(from, x);
dbgcol(BLUE) dbgcol(GREEN)
dbg3dline(from, y); dbg3dline(from, y);
dbgcol(YELLOW) dbgcol(BLUE)
dbg3dline(from, z); dbg3dline(from, z);
dbgcol(YELLOW)
dbg3dline(from, dot);
dbgcol(PINK)
dbgsquare3d(dot);
cur_pose_bone = cur_pose_bone->next; cur_pose_bone = cur_pose_bone->next;
} }
@ -6334,7 +6426,7 @@ void frame(void)
Vec2 pos = V2(0.0, screen_size().Y); Vec2 pos = V2(0.0, screen_size().Y);
int num_entities = 0; int num_entities = 0;
ENTITIES_ITER(gs.entities) num_entities++; ENTITIES_ITER(gs.entities) num_entities++;
MD_String8 stats = tprint("Frametime: %.1f ms\nProcessing: %.1f ms\nGameplay processing: %.1f ms\nEntities: %d\nDraw calls: %d\nDrawn Vertices: %d\nProfiling: %s\nNumber gameplay processing loops: %d\nFlyecam: %s\n", dt*1000.0, last_frame_processing_time*1000.0, last_frame_gameplay_processing_time*1000.0, num_entities, num_draw_calls, num_vertices, profiling ? "yes" : "no", num_timestep_loops, flycam ? "yes" : "no"); MD_String8 stats = tprint("Frametime: %.1f ms\nProcessing: %.1f ms\nGameplay processing: %.1f ms\nEntities: %d\nDraw calls: %d\nDrawn Vertices: %d\nProfiling: %s\nNumber gameplay processing loops: %d\nFlyecam: %s\nPlayer position: %f %f\n", dt*1000.0, last_frame_processing_time*1000.0, last_frame_gameplay_processing_time*1000.0, num_entities, num_draw_calls, num_vertices, profiling ? "yes" : "no", num_timestep_loops, flycam ? "yes" : "no", v2varg(gs.player->pos));
AABB bounds = draw_text((TextParams) { true, stats, pos, BLACK, 1.0f }); AABB bounds = draw_text((TextParams) { true, stats, pos, BLACK, 1.0f });
pos.Y -= bounds.upper_left.Y - screen_size().Y; pos.Y -= bounds.upper_left.Y - screen_size().Y;
bounds = draw_text((TextParams) { true, stats, pos, BLACK, 1.0f }); bounds = draw_text((TextParams) { true, stats, pos, BLACK, 1.0f });

@ -16,6 +16,7 @@ mkdir gen
@REM shaders @REM shaders
thirdparty\sokol-shdc.exe --input quad.glsl --output gen\quad-sapp.glsl.h --slang glsl100:hlsl5:metal_macos:glsl330 || goto :error thirdparty\sokol-shdc.exe --input quad.glsl --output gen\quad-sapp.glsl.h --slang glsl100:hlsl5:metal_macos:glsl330 || goto :error
thirdparty\sokol-shdc.exe --input threedee.glsl --output gen\threedee.glsl.h --slang glsl100:hlsl5:metal_macos:glsl330 || goto :error thirdparty\sokol-shdc.exe --input threedee.glsl --output gen\threedee.glsl.h --slang glsl100:hlsl5:metal_macos:glsl330 || goto :error
thirdparty\sokol-shdc.exe --input armature.glsl --output gen\armature.glsl.h --slang glsl100:hlsl5:metal_macos:glsl330 || goto :error
@REM metadesk codegen @REM metadesk codegen
cl /Ithirdparty /W3 /Zi /WX codegen.c || goto :error cl /Ithirdparty /W3 /Zi /WX codegen.c || goto :error

Loading…
Cancel
Save