diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 6c6cdca663..993f15c42a 100644 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -18,6 +18,8 @@ from os import listdir import untangle import zipfile + +## Base implementation for reading 3MF files. Has no support for textures. Only loads meshes! class ThreeMFReader(MeshReader): def __init__(self): super(ThreeMFReader, self).__init__() @@ -28,11 +30,12 @@ class ThreeMFReader(MeshReader): extension = os.path.splitext(file_name)[1] if extension.lower() == self._supported_extension: result = SceneNode() + # The base object of 3mf is a zipped archive. archive = zipfile.ZipFile(file_name, 'r') - #print(archive.read("3D/3dmodel.model")) try: + # The model is always stored in this place. root = untangle.parse(archive.read("3D/3dmodel.model").decode("utf-8")) - for object in root.model.resources.object: + for object in root.model.resources.object: # There can be multiple objects, try to load all of them. mesh = MeshData() node = SceneNode() vertex_list = [] @@ -40,19 +43,22 @@ class ThreeMFReader(MeshReader): vertex_list.append([vertex['x'],vertex['y'],vertex['z']]) mesh.reserveFaceCount(len(object.mesh.triangles.triangle)) + for triangle in object.mesh.triangles.triangle: v1 = int(triangle["v1"]) v2 = int(triangle["v2"]) v3 = int(triangle["v3"]) mesh.addFace(vertex_list[v1][0],vertex_list[v1][1],vertex_list[v1][2],vertex_list[v2][0],vertex_list[v2][1],vertex_list[v2][2],vertex_list[v3][0],vertex_list[v3][1],vertex_list[v3][2]) + #TODO: We currently do not check for normals and simply recalculate them. mesh.calculateNormals() node.setMeshData(mesh) node.setSelectable(True) + # Magical python comprehension; looks for the matching transformation transformation = next((x for x in root.model.build.item if x["objectid"] == object["id"]), None) + if transformation["transform"]: - splitted_transformation = transformation["transform"].split() - + splitted_transformation = transformation["transform"].split() ## Transformation is saved as: ## M00 M01 M02 0.0 ## M10 M11 M12 0.0 @@ -60,18 +66,18 @@ class ThreeMFReader(MeshReader): ## M30 M31 M32 1.0 ## We switch the row & cols as that is how everyone else uses matrices! temp_mat = Matrix() + # Rotation & Scale temp_mat._data[0,0] = splitted_transformation[0] temp_mat._data[1,0] = splitted_transformation[1] temp_mat._data[2,0] = splitted_transformation[2] - temp_mat._data[0,1] = splitted_transformation[3] temp_mat._data[1,1] = splitted_transformation[4] temp_mat._data[2,1] = splitted_transformation[5] - temp_mat._data[0,2] = splitted_transformation[6] temp_mat._data[1,2] = splitted_transformation[7] temp_mat._data[2,2] = splitted_transformation[8] + # Translation temp_mat._data[0,3] = splitted_transformation[9] temp_mat._data[1,3] = splitted_transformation[10] temp_mat._data[2,3] = splitted_transformation[11] @@ -89,13 +95,12 @@ class ThreeMFReader(MeshReader): scale_z = math.sqrt(S2.at(2,2)) node.setScale(Vector(scale_x,scale_y,scale_z)) - # We use a different coordinate frame, so rotate. rotation = Quaternion.fromAngleAxis(-0.5 * math.pi, Vector(1,0,0)) node.rotate(rotation) result.addChild(node) - # If there is more then one object, group them. + # If there is more then one object, group them. try: if len(root.model.resources.object) > 1: group_decorator = GroupDecorator() @@ -103,5 +108,5 @@ class ThreeMFReader(MeshReader): except: pass except Exception as e: - print("EXCEPTION: " ,e) + Logger.log("e" ,"exception occured in 3mf reader: %s" , e) return result