diff --git a/additional_file_formats/__init__.py b/additional_file_formats/__init__.py index 4d0b7e7..ebea389 100644 --- a/additional_file_formats/__init__.py +++ b/additional_file_formats/__init__.py @@ -1,2 +1,3 @@ from . import bgeo -from . import mzd \ No newline at end of file +from . import mzd +from . import bin \ No newline at end of file diff --git a/additional_file_formats/bin.py b/additional_file_formats/bin.py new file mode 100644 index 0000000..c1caf1b --- /dev/null +++ b/additional_file_formats/bin.py @@ -0,0 +1,117 @@ +import bpy +import mathutils +import re +import os +import struct +import meshio +from math import radians + +def readBIN_to_meshio(filepath): + firstFile = open(filepath, 'rb') + + # read number of bodies + bytes = firstFile.read() + firstFile.close() + + isFirstFile = ((len(bytes) % 48) != 0) + + # currently assume that numBodies is always 1 + (numBodies,), bytes = struct.unpack('i', bytes[:4]), bytes[4:] + numBodies *= isFirstFile + + field_datas = [] + for i in range(0, numBodies): + # determine length of file name string + (strLength,), bytes = struct.unpack('i', bytes[:4]), bytes[4:] + + # read file name + objFile, bytes = bytes[:strLength], bytes[strLength:] + if i == 0: + objFileString = objFile.decode('ascii') + + cur_field_data = {} + cur_field_data["translation"] = None + cur_field_data["scaling"] = None + cur_field_data["rotation"] = None + cur_field_data["transformation_matrix"] = None + + # Read scaling factors in first file + (sx,), bytes = struct.unpack('f', bytes[:4]), bytes[4:] + (sy,), bytes = struct.unpack('f', bytes[:4]), bytes[4:] + (sz,), bytes = struct.unpack('f', bytes[:4]), bytes[4:] + + cur_field_data["scaling"] = (sx, sy, sz) + + (isWall,), bytes = struct.unpack('?', bytes[:1]), bytes[1:] + (colr,), bytes = struct.unpack('f', bytes[:4]), bytes[4:] + (colg,), bytes = struct.unpack('f', bytes[:4]), bytes[4:] + (colb,), bytes = struct.unpack('f', bytes[:4]), bytes[4:] + (cola,), bytes = struct.unpack('f', bytes[:4]), bytes[4:] + + field_datas.append(cur_field_data) + + # if the object name is empty, then we know that it is not a "first file" + # and we just simply reopen it and start from the beginning + if isFirstFile: + # create mesh from referenced object + dirPath = os.path.dirname(filepath) + objPath = os.path.join(dirPath, objFileString) + + mesh = meshio.read(objPath) + else: + otherFile = open(filepath, 'rb') + + # reopen same file + bytes = otherFile.read() + otherFile.close() + + # since there is no object referenced, create empty mesh + mesh = meshio.Mesh([], []) + + i = 0 + while len(bytes) != 0: + cur_field_data = {} + cur_field_data["translation"] = None + cur_field_data["scaling"] = (1, 1, 1) + cur_field_data["rotation"] = None + cur_field_data["transformation_matrix"] = None + + # Read translation in first file + (x,), bytes = struct.unpack('f', bytes[:4]), bytes[4:] + (y,), bytes = struct.unpack('f', bytes[:4]), bytes[4:] + (z,), bytes = struct.unpack('f', bytes[:4]), bytes[4:] + + cur_field_data["translation"] = (x, y, z) + + # Read rotation in first file + r = [] + for _ in range(0,9): + (value,), bytes = struct.unpack('f', bytes[:4]), bytes[4:] + r.append(value) + + rotationMatrix = mathutils.Matrix() + rotationMatrix[0][0:3] = r[0], r[3], r[6] + rotationMatrix[1][0:3] = r[1], r[4], r[7] + rotationMatrix[2][0:3] = r[2], r[5], r[8] + + cur_field_data["rotation"] = rotationMatrix.to_quaternion() + cur_field_data["transformation_matrix"] = mathutils.Matrix.LocRotScale( + cur_field_data["translation"], + cur_field_data["rotation"], + cur_field_data["scaling"]) + + if isFirstFile: + field_datas[i]["translation"] = cur_field_data["translation"] + field_datas[i]["rotation"] = cur_field_data["rotation"] + field_datas[i]["transformation_matrix"] = cur_field_data["transformation_matrix"] + else: + field_datas.append(cur_field_data) + + i += 1 + + mesh.field_data = field_datas[0] + + return mesh + +# no need for write function +meshio.register_format("bin", [".bin"], readBIN_to_meshio, {".bin": None}) \ No newline at end of file diff --git a/bseq/importer.py b/bseq/importer.py index d5dbc93..8a7b28d 100644 --- a/bseq/importer.py +++ b/bseq/importer.py @@ -63,8 +63,8 @@ def has_keyframe(obj, attr): def apply_transformation(meshio_mesh, obj, depsgraph): # evaluate the keyframe animation system - eval_location = obj.evaluated_get(depsgraph).location if has_keyframe(obj, "location") else None - eval_scale = obj.evaluated_get(depsgraph).scale if has_keyframe(obj, "scale") else None + eval_location = obj.evaluated_get(depsgraph).location if has_keyframe(obj, "location") else obj.location + eval_scale = obj.evaluated_get(depsgraph).scale if has_keyframe(obj, "scale") else obj.scale if has_keyframe(obj, "rotation_quaternion"): eval_rotation = obj.evaluated_get(depsgraph).rotation_quaternion @@ -73,7 +73,7 @@ def apply_transformation(meshio_mesh, obj, depsgraph): elif has_keyframe(obj, "rotation_euler"): eval_rotation = obj.evaluated_get(depsgraph).rotation_euler else: - eval_rotation = None + eval_rotation = obj.rotation_euler eval_transform_matrix = mathutils.Matrix.LocRotScale(eval_location, eval_rotation, eval_scale) @@ -83,7 +83,7 @@ def apply_transformation(meshio_mesh, obj, depsgraph): rigid_body_transformation = meshio_mesh.field_data["transformation_matrix"] # multiply everything together (with custom transform matrix) - obj.matrix_world = rigid_body_transformation @ obj.BSEQ.initial_transform_matrix @ eval_transform_matrix + obj.matrix_world = rigid_body_transformation @ eval_transform_matrix def update_mesh(meshio_mesh, mesh): # extract information from the meshio mesh @@ -220,7 +220,8 @@ def create_obj(fileseq, use_relative, root_path, transform_matrix=Matrix([[1, 0, object.BSEQ.init = True object.BSEQ.enabled = enabled # Flatten custom transformation matrix for the property - object.BSEQ.initial_transform_matrix = [transform_matrix[j][i] for i in range(4) for j in range(4)] + #object.BSEQ.initial_transform_matrix = [transform_matrix[j][i] for i in range(4) for j in range(4)] + object.matrix_world = transform_matrix driver = object.driver_add("BSEQ.frame") driver.driver.expression = 'frame' if enabled: