diff options
author | Ghostkeeper <rubend@tutanota.com> | 2019-08-29 15:56:49 +0300 |
---|---|---|
committer | Ghostkeeper <rubend@tutanota.com> | 2019-08-29 15:57:55 +0300 |
commit | 1f534db50838b311d2ea6eff880df90634027c08 (patch) | |
tree | f7e3f1089c139bcba18d66754458e55371249b6a /plugins/TrimeshReader | |
parent | cead90c5bacdb519c93b020fb1cce13d64706042 (diff) |
Handle Trimesh returning scene of objects
These objects are added as a group node, if they are plural.
Contributes to issue CURA-6739.
Diffstat (limited to 'plugins/TrimeshReader')
-rw-r--r-- | plugins/TrimeshReader/TrimeshReader.py | 58 |
1 files changed, 43 insertions, 15 deletions
diff --git a/plugins/TrimeshReader/TrimeshReader.py b/plugins/TrimeshReader/TrimeshReader.py index d719e3dbc8..f0fd9bc023 100644 --- a/plugins/TrimeshReader/TrimeshReader.py +++ b/plugins/TrimeshReader/TrimeshReader.py @@ -3,6 +3,7 @@ # The _toMeshData function is taken from the AMFReader class which was built by fieldOfView. +from typing import List, Union, TYPE_CHECKING import numpy # To create the mesh data. import os.path # To create the mesh name for the resulting mesh. import trimesh # To load the files into a Trimesh. @@ -10,12 +11,17 @@ import trimesh # To load the files into a Trimesh. from UM.Mesh.MeshData import MeshData, calculateNormalsFromIndexedVertices # To construct meshes from the Trimesh data. from UM.Mesh.MeshReader import MeshReader # The plug-in type we're extending. from UM.MimeTypeDatabase import MimeTypeDatabase, MimeType # To add file types that we can open. +from UM.Scene.GroupDecorator import GroupDecorator # Added to the parent node if we load multiple nodes at once. from cura.CuraApplication import CuraApplication from cura.Scene.BuildPlateDecorator import BuildPlateDecorator # Added to the resulting scene node. +from cura.Scene.ConvexHullDecorator import ConvexHullDecorator # Added to group nodes if we load multiple nodes at once. from cura.Scene.CuraSceneNode import CuraSceneNode # To create a node in the scene after reading the file. from cura.Scene.SliceableObjectDecorator import SliceableObjectDecorator # Added to the resulting scene node. +if TYPE_CHECKING: + from UM.Scene.SceneNode import SceneNode + ## Class that leverages Trimesh to import files. class TrimeshReader(MeshReader): def __init__(self) -> None: @@ -34,21 +40,43 @@ class TrimeshReader(MeshReader): # \param file_name The file path. This is assumed to be one of the file # types that Trimesh can read. It will not be checked again. # \return A scene node that contains the file's contents. - def _read(self, file_name: str) -> CuraSceneNode: - mesh = trimesh.load(file_name) - mesh.merge_vertices() - mesh.remove_unreferenced_vertices() - mesh.fix_normals() - mesh_data = self._toMeshData(mesh) - - file_base_name = os.path.basename(file_name) - new_node = CuraSceneNode() - new_node.setMeshData(mesh_data) - new_node.setSelectable(True) - new_node.setName(file_base_name) - new_node.addDecorator(BuildPlateDecorator(CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate)) - new_node.addDecorator(SliceableObjectDecorator()) - return new_node + def _read(self, file_name: str) -> Union["SceneNode", List["SceneNode"]]: + mesh_or_scene = trimesh.load(file_name) + meshes = [] + if isinstance(mesh_or_scene, trimesh.Trimesh): + meshes = [mesh_or_scene] + elif isinstance(mesh_or_scene, trimesh.Scene): + meshes = [mesh for mesh in mesh_or_scene.geometry.values()] + + active_build_plate = CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate + nodes = [] + for mesh in meshes: + if not isinstance(mesh, trimesh.Trimesh): # Trimesh can also receive point clouds, 2D paths, 3D paths or metadata. Skip those. + continue + mesh.merge_vertices() + mesh.remove_unreferenced_vertices() + mesh.fix_normals() + mesh_data = self._toMeshData(mesh) + + file_base_name = os.path.basename(file_name) + new_node = CuraSceneNode() + new_node.setMeshData(mesh_data) + new_node.setSelectable(True) + new_node.setName(file_base_name if len(meshes) == 1 else "{file_base_name} {counter}".format(file_base_name = file_base_name, counter = str(len(nodes) + 1))) + new_node.addDecorator(BuildPlateDecorator(active_build_plate)) + new_node.addDecorator(SliceableObjectDecorator()) + nodes.append(new_node) + + if len(nodes) == 1: + return nodes[0] + # Add all nodes to a group so they stay together. + group_node = CuraSceneNode() + group_node.addDecorator(GroupDecorator()) + group_node.addDecorator(ConvexHullDecorator()) + group_node.addDecorator(BuildPlateDecorator(active_build_plate)) + for node in nodes: + node.setParent(group_node) + return group_node ## Converts a Trimesh to Uranium's MeshData. # \param tri_node A Trimesh containing the contents of a file that was |