Export armature as bones, import and debug draw in 3d. Flipped coord

systems right now.
main
parent 89070ed9e0
commit 76d209f0b4

@ -30,6 +30,11 @@ def write_string(f, s: str):
write_u64(f, len(encoded))
f.write(encoded)
def write_4x4matrix(f, m):
# writes each row, sequentially, row major
for row in range(4):
for col in range(4):
write_f32(f, m[row][col])
# for the level.bin
level_object_data = []
@ -37,64 +42,78 @@ collision_cubes = []
placed_entities = []
saved_meshes = set()
mapping = axis_conversion(
from_forward = "Y",
from_up = "Z",
to_forward = "-Z",
to_up = "Y",
)
for o in D.objects:
mapping = axis_conversion(
from_forward = "Y",
from_up = "Z",
to_forward = "-Z",
to_up = "Y",
)
mesh_name = o.to_mesh().name # use this over o.name so instanced objects which refer to the same mesh, both use the same serialized mesh.
object_transform_info = (mesh_name, mapping @ o.location, o.rotation_euler, o.scale)
if o.users_collection[0].name == 'Level' and mesh_name == "CollisionCube":
collision_cubes.append((o.location, o.dimensions))
else:
if o.users_collection[0].name == 'Level':
print(f"Object {o.name} has mesh name {o.to_mesh().name}")
assert(o.rotation_euler.order == 'XYZ')
level_object_data.append(object_transform_info)
if o.type == "ARMATURE":
armature_name = o.data.name
output_filepath = bpy.path.abspath(f"//{EXPORT_DIRECTORY}/{armature_name}.bin")
print(f"Exporting armature to {output_filepath}")
with open(output_filepath, "wb") as f:
write_u64(f, len(o.data.bones))
for b in o.data.bones:
in_game_coordinate_system = mapping @ b.matrix_local
write_4x4matrix(f, b.matrix_local)
elif o.type == "MESH":
mesh_name = o.to_mesh().name # use this over o.name so instanced objects which refer to the same mesh, both use the same serialized mesh.
object_transform_info = (mesh_name, mapping @ o.location, o.rotation_euler, o.scale)
if o.users_collection[0].name == 'Level' and mesh_name == "CollisionCube":
collision_cubes.append((o.location, o.dimensions))
else:
if o.users_collection[0].name == 'Level':
print(f"Object {o.name} has mesh name {o.to_mesh().name}")
assert(o.rotation_euler.order == 'XYZ')
level_object_data.append(object_transform_info)
else:
placed_entities.append((o.name,) + object_transform_info)
if mesh_name in saved_meshes:
continue
saved_meshes.add(mesh_name)
else:
placed_entities.append((o.name,) + object_transform_info)
mapping.resize_4x4()
assert(mesh_name != LEVEL_EXPORT_NAME)
output_filepath = bpy.path.abspath(f"//{EXPORT_DIRECTORY}/{mesh_name}.bin")
print(f"Exporting {output_filepath}")
with open(output_filepath, "wb") as f:
bm = bmesh.new()
mesh = o.to_mesh()
bm.from_mesh(mesh)
bmesh.ops.triangulate(bm, faces=bm.faces)
bm.transform(mapping)
bm.to_mesh(mesh)
vertices = []
mapping.resize_4x4()
assert(mesh_name != LEVEL_EXPORT_NAME)
output_filepath = bpy.path.abspath(f"//{EXPORT_DIRECTORY}/{mesh_name}.bin")
print(f"Exporting mesh to {output_filepath}")
with open(output_filepath, "wb") as f:
bm = bmesh.new()
mesh = o.to_mesh()
bm.from_mesh(mesh)
bmesh.ops.triangulate(bm, faces=bm.faces)
bm.transform(mapping)
bm.to_mesh(mesh)
vertices = []
for polygon in mesh.polygons:
if len(polygon.loop_indices) == 3:
for loopIndex in polygon.loop_indices:
loop = mesh.loops[loopIndex]
position = mesh.vertices[loop.vertex_index].undeformed_co
uv = mesh.uv_layers.active.data[loop.index].uv
normal = loop.normal
vertices.append((position, uv))
write_u64(f, len(vertices))
for v_and_uv in vertices:
v, uv = v_and_uv
write_f32(f, v.x)
write_f32(f, v.y)
write_f32(f, v.z)
write_f32(f, uv.x)
write_f32(f, uv.y)
print(f"Wrote {len(vertices)} vertices")
for polygon in mesh.polygons:
if len(polygon.loop_indices) == 3:
for loopIndex in polygon.loop_indices:
loop = mesh.loops[loopIndex]
position = mesh.vertices[loop.vertex_index].undeformed_co
uv = mesh.uv_layers.active.data[loop.index].uv
normal = loop.normal
vertices.append((position, uv))
write_u64(f, len(vertices))
for v_and_uv in vertices:
v, uv = v_and_uv
write_f32(f, v.x)
write_f32(f, v.y)
write_f32(f, v.z)
write_f32(f, uv.x)
write_f32(f, uv.y)
print(f"Wrote {len(vertices)} vertices")
with open(bpy.path.abspath(f"//{EXPORT_DIRECTORY}/{LEVEL_EXPORT_NAME}.bin"), "wb") as f:
write_u64(f, len(level_object_data))
@ -140,4 +159,5 @@ with open(bpy.path.abspath(f"//{EXPORT_DIRECTORY}/{LEVEL_EXPORT_NAME}.bin"), "wb
write_f32(f, blender_scale.x)
write_f32(f, blender_scale.y)
write_f32(f, blender_scale.z)
write_f32(f, blender_scale.z)

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

Binary file not shown.

@ -811,6 +811,12 @@ typedef struct Mesh
MD_String8 name;
} Mesh;
typedef struct Bone
{
struct Bone *next;
Mat4 matrix_local;
} Bone;
typedef struct
{
Vec3 offset;
@ -879,6 +885,59 @@ Mesh load_mesh(MD_Arena *arena, MD_String8 binary_file, MD_String8 mesh_name)
return out;
}
// stored in row major
typedef struct
{
float elems[4 * 4];
} BlenderMat;
void ser_BlenderMat(SerState *ser, BlenderMat *b)
{
for(int i = 0; i < 4 * 4; i++)
{
ser_float(ser, &b->elems[i]);
}
}
Mat4 blender_to_handmade_mat(BlenderMat b)
{
Mat4 to_return;
assert(sizeof(to_return) == sizeof(b));
memcpy(&to_return, &b, sizeof(to_return));
return TransposeM4(to_return);
}
Bone *load_armature(MD_Arena *arena, MD_String8 binary_file, MD_String8 armature_name)
{
MD_ArenaTemp scratch = MD_GetScratch(&arena, 1);
SerState ser = {
.data = binary_file.str,
.max = binary_file.size,
.arena = arena,
.error_arena = scratch.arena,
.serializing = false,
};
Bone *to_return = 0;
MD_u64 num_bones;
ser_MD_u64(&ser, &num_bones);
Log("Armature %.*s has %llu vertices\n", MD_S8VArg(armature_name), num_bones);
for(MD_u64 i = 0; i < num_bones; i++)
{
Bone *next_bone = MD_PushArray(arena, Bone, 1);
BlenderMat b;
ser_BlenderMat(&ser, &b);
next_bone->matrix_local = blender_to_handmade_mat(b);
MD_StackPush(to_return, next_bone);
}
assert(!ser.cur_error.failed);
MD_ReleaseScratch(scratch);
return to_return;
}
typedef struct CollisionCube
{
struct CollisionCube *next;
@ -900,6 +959,7 @@ void ser_BlenderTransform(SerState *ser, BlenderTransform *t)
ser_Vec3(ser, &t->scale);
}
Transform blender_to_game_transform(BlenderTransform blender_transform)
{
Transform to_return = {0};
@ -1058,6 +1118,11 @@ Vec4 IsPoint(Vec3 point)
return V4(point.x, point.y, point.z, 1.0f);
}
Vec3 MulM4V3(Mat4 m, Vec3 v)
{
return MulM4V4(m, IsPoint(v)).xyz;
}
typedef struct
{
Vec3 right; // X+
@ -2606,6 +2671,7 @@ void do_serialization_tests()
}
#endif
Bone *bones = 0;
Mesh mesh_player = {0};
void stbi_flip_into_correct_direction(bool do_it)
@ -2655,6 +2721,8 @@ void init(void)
MD_String8 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"));
binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/Armature.bin"));
bones = load_armature(persistent_arena, binary_file, MD_S8Lit("Player.bin"));
MD_ArenaClear(frame_arena);
binary_file = MD_LoadEntireFile(frame_arena, MD_S8Lit("assets/exported_3d/level.bin"));
@ -4406,6 +4474,22 @@ void frame(void)
}
projection = Perspective_RH_NO(PI32/4.0f, screen_size().x / screen_size().y, 0.01f, 1000.0f);
for(Bone *cur = bones; cur; cur = cur->next)
{
Vec3 offset = V3(5, 0, 5);
if(cur->next)
{
Vec3 from = MulM4V3(cur->matrix_local, V3(0,0,0));
Vec3 to = MulM4V3(cur->next->matrix_local, V3(0,0,0));
from = AddV3(from, offset);
to = AddV3(to, offset);
dbgcol(BLUE)
dbg3dline(from, to);
}
}
for(PlacedMesh *cur = level_threedee.placed_mesh_list; cur; cur = cur->next)
{
draw_placed(view, projection, cur);

Loading…
Cancel
Save