def test_reserveVertexCount(): builder = MeshBuilder() builder.addVertex(1, 2, 3) builder.reserveVertexCount(10) # Reserving face count should reset the verts assert builder.getVertexCount() == 0
def test_getTransformedMeshdata(self): node = SceneNode() node.translate(Vector(10, 0, 0)) builder = MeshBuilder() builder.addVertex(10, 20, 20) node.setMeshData(builder.build()) transformed_mesh = node.getMeshDataTransformed() transformed_vertex = transformed_mesh.getVertices()[0] assert transformed_vertex[0] == 20 assert transformed_vertex[1] == 20 assert transformed_vertex[2] == 20
def __init__(self): super().__init__() self.scale_factor = 50 builder = MeshBuilder() builder.addQuad(Vector(-self.scale_factor, -self.scale_factor, 0), Vector(self.scale_factor, -self.scale_factor, 0), Vector(self.scale_factor, self.scale_factor, 0), Vector(-self.scale_factor, self.scale_factor, 0)) builder.addVertex(0, 0, 0.0001) mesh = builder.build() self.setMeshData(mesh) self.setSelectable(True) self.setName("Plane")
def test_setCenterPosition(self): node = SceneNode() child_node = SceneNode() node.addChild(child_node) child_node.setCenterPosition = MagicMock() builder = MeshBuilder() builder.addVertex(10, 20, 20) node.setMeshData(builder.build()) node.setCenterPosition(Vector(-10, 0, 0)) transformed_mesh = node.getMeshData() transformed_vertex = transformed_mesh.getVertices()[0] assert transformed_vertex[0] == 20 assert transformed_vertex[1] == 20 assert transformed_vertex[2] == 20 child_node.setCenterPosition.assert_called_once_with(Vector(-10, 0, 0))
def calculateBoundingBoxMesh(self): aabb = self.getBoundingBox() if aabb: bounding_box_mesh = MeshBuilder() rtf = aabb.maximum lbb = aabb.minimum bounding_box_mesh.addVertex(rtf.x, rtf.y, rtf.z) # Right - Top - Front bounding_box_mesh.addVertex(lbb.x, rtf.y, rtf.z) # Left - Top - Front bounding_box_mesh.addVertex(lbb.x, rtf.y, rtf.z) # Left - Top - Front bounding_box_mesh.addVertex(lbb.x, lbb.y, rtf.z) # Left - Bottom - Front bounding_box_mesh.addVertex(lbb.x, lbb.y, rtf.z) # Left - Bottom - Front bounding_box_mesh.addVertex(rtf.x, lbb.y, rtf.z) # Right - Bottom - Front bounding_box_mesh.addVertex(rtf.x, lbb.y, rtf.z) # Right - Bottom - Front bounding_box_mesh.addVertex(rtf.x, rtf.y, rtf.z) # Right - Top - Front bounding_box_mesh.addVertex(rtf.x, rtf.y, lbb.z) # Right - Top - Back bounding_box_mesh.addVertex(lbb.x, rtf.y, lbb.z) # Left - Top - Back bounding_box_mesh.addVertex(lbb.x, rtf.y, lbb.z) # Left - Top - Back bounding_box_mesh.addVertex(lbb.x, lbb.y, lbb.z) # Left - Bottom - Back bounding_box_mesh.addVertex(lbb.x, lbb.y, lbb.z) # Left - Bottom - Back bounding_box_mesh.addVertex(rtf.x, lbb.y, lbb.z) # Right - Bottom - Back bounding_box_mesh.addVertex(rtf.x, lbb.y, lbb.z) # Right - Bottom - Back bounding_box_mesh.addVertex(rtf.x, rtf.y, lbb.z) # Right - Top - Back bounding_box_mesh.addVertex(rtf.x, rtf.y, rtf.z) # Right - Top - Front bounding_box_mesh.addVertex(rtf.x, rtf.y, lbb.z) # Right - Top - Back bounding_box_mesh.addVertex(lbb.x, rtf.y, rtf.z) # Left - Top - Front bounding_box_mesh.addVertex(lbb.x, rtf.y, lbb.z) # Left - Top - Back bounding_box_mesh.addVertex(lbb.x, lbb.y, rtf.z) # Left - Bottom - Front bounding_box_mesh.addVertex(lbb.x, lbb.y, lbb.z) # Left - Bottom - Back bounding_box_mesh.addVertex(rtf.x, lbb.y, rtf.z) # Right - Bottom - Front bounding_box_mesh.addVertex(rtf.x, lbb.y, lbb.z) # Right - Bottom - Back self._bounding_box_mesh = bounding_box_mesh.build()
def test_setVertexColor(): builder = MeshBuilder() builder.addVertex(1, 2, 3) builder.setVertexColor(0, Color(1.0, 0.5, 0.2)) assert builder.hasColors() assert builder.getColors()[0][0] == 1.0
def rebuild(self): if not self._width or not self._height or not self._depth: return min_w = -self._width / 2 max_w = self._width / 2 min_h = 0.0 max_h = self._height min_d = -self._depth / 2 max_d = self._depth / 2 z_fight_distance = 0.2 # Distance between buildplate and disallowed area meshes to prevent z-fighting if self._shape != "elliptic": # Outline 'cube' of the build volume mb = MeshBuilder() mb.addLine(Vector(min_w, min_h, min_d), Vector(max_w, min_h, min_d), color = self.VolumeOutlineColor) mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, max_h, min_d), color = self.VolumeOutlineColor) mb.addLine(Vector(min_w, max_h, min_d), Vector(max_w, max_h, min_d), color = self.VolumeOutlineColor) mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, max_h, min_d), color = self.VolumeOutlineColor) mb.addLine(Vector(min_w, min_h, max_d), Vector(max_w, min_h, max_d), color = self.VolumeOutlineColor) mb.addLine(Vector(min_w, min_h, max_d), Vector(min_w, max_h, max_d), color = self.VolumeOutlineColor) mb.addLine(Vector(min_w, max_h, max_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor) mb.addLine(Vector(max_w, min_h, max_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor) mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, min_h, max_d), color = self.VolumeOutlineColor) mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, min_h, max_d), color = self.VolumeOutlineColor) mb.addLine(Vector(min_w, max_h, min_d), Vector(min_w, max_h, max_d), color = self.VolumeOutlineColor) mb.addLine(Vector(max_w, max_h, min_d), Vector(max_w, max_h, max_d), color = self.VolumeOutlineColor) self.setMeshData(mb.build()) # Build plate grid mesh mb = MeshBuilder() mb.addQuad( Vector(min_w, min_h - z_fight_distance, min_d), Vector(max_w, min_h - z_fight_distance, min_d), Vector(max_w, min_h - z_fight_distance, max_d), Vector(min_w, min_h - z_fight_distance, max_d) ) for n in range(0, 6): v = mb.getVertex(n) mb.setVertexUVCoordinates(n, v[0], v[2]) self._grid_mesh = mb.build() else: # Bottom and top 'ellipse' of the build volume aspect = 1.0 scale_matrix = Matrix() if self._width != 0: # Scale circular meshes by aspect ratio if width != height aspect = self._height / self._width scale_matrix.compose(scale = Vector(1, 1, aspect)) mb = MeshBuilder() mb.addArc(max_w, Vector.Unit_Y, center = (0, min_h - z_fight_distance, 0), color = self.VolumeOutlineColor) mb.addArc(max_w, Vector.Unit_Y, center = (0, max_h, 0), color = self.VolumeOutlineColor) self.setMeshData(mb.build().getTransformed(scale_matrix)) # Build plate grid mesh mb = MeshBuilder() mb.addVertex(0, min_h - z_fight_distance, 0) mb.addArc(max_w, Vector.Unit_Y, center = Vector(0, min_h - z_fight_distance, 0)) sections = mb.getVertexCount() - 1 # Center point is not an arc section indices = [] for n in range(0, sections - 1): indices.append([0, n + 2, n + 1]) mb.addIndices(numpy.asarray(indices, dtype = numpy.int32)) mb.calculateNormals() for n in range(0, mb.getVertexCount()): v = mb.getVertex(n) mb.setVertexUVCoordinates(n, v[0], v[2] * aspect) self._grid_mesh = mb.build().getTransformed(scale_matrix) # Indication of the machine origin if self._global_container_stack.getProperty("machine_center_is_zero", "value"): origin = (Vector(min_w, min_h, min_d) + Vector(max_w, min_h, max_d)) / 2 else: origin = Vector(min_w, min_h, max_d) mb = MeshBuilder() mb.addCube( width = self._origin_line_length, height = self._origin_line_width, depth = self._origin_line_width, center = origin + Vector(self._origin_line_length / 2, 0, 0), color = self.XAxisColor ) mb.addCube( width = self._origin_line_width, height = self._origin_line_length, depth = self._origin_line_width, center = origin + Vector(0, self._origin_line_length / 2, 0), color = self.YAxisColor ) mb.addCube( width = self._origin_line_width, height = self._origin_line_width, depth = self._origin_line_length, center = origin - Vector(0, 0, self._origin_line_length / 2), color = self.ZAxisColor ) self._origin_mesh = mb.build() disallowed_area_height = 0.1 disallowed_area_size = 0 if self._disallowed_areas: mb = MeshBuilder() color = Color(0.0, 0.0, 0.0, 0.15) for polygon in self._disallowed_areas: points = polygon.getPoints() first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._clamp(points[0][1], min_d, max_d)) previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._clamp(points[0][1], min_d, max_d)) for point in points: new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height, self._clamp(point[1], min_d, max_d)) mb.addFace(first, previous_point, new_point, color = color) previous_point = new_point # Find the largest disallowed area to exclude it from the maximum scale bounds. # This is a very nasty hack. This pretty much only works for UM machines. # This disallowed area_size needs a -lot- of rework at some point in the future: TODO if numpy.min(points[:, 1]) >= 0: # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area. size = abs(numpy.max(points[:, 1]) - numpy.min(points[:, 1])) else: size = 0 disallowed_area_size = max(size, disallowed_area_size) self._disallowed_area_mesh = mb.build() else: self._disallowed_area_mesh = None if self._error_areas: mb = MeshBuilder() for error_area in self._error_areas: color = Color(1.0, 0.0, 0.0, 0.5) points = error_area.getPoints() first = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._clamp(points[0][1], min_d, max_d)) previous_point = Vector(self._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._clamp(points[0][1], min_d, max_d)) for point in points: new_point = Vector(self._clamp(point[0], min_w, max_w), disallowed_area_height, self._clamp(point[1], min_d, max_d)) mb.addFace(first, previous_point, new_point, color=color) previous_point = new_point self._error_mesh = mb.build() else: self._error_mesh = None self._volume_aabb = AxisAlignedBox( minimum = Vector(min_w, min_h - 1.0, min_d), maximum = Vector(max_w, max_h - self._raft_thickness, max_d)) bed_adhesion_size = self._getEdgeDisallowedSize() # As this works better for UM machines, we only add the disallowed_area_size for the z direction. # This is probably wrong in all other cases. TODO! # The +1 and -1 is added as there is always a bit of extra room required to work properly. scale_to_max_bounds = AxisAlignedBox( minimum = Vector(min_w + bed_adhesion_size + 1, min_h, min_d + disallowed_area_size - bed_adhesion_size + 1), maximum = Vector(max_w - bed_adhesion_size - 1, max_h - self._raft_thickness, max_d - disallowed_area_size + bed_adhesion_size - 1) ) Application.getInstance().getController().getScene()._maximum_bounds = scale_to_max_bounds
def _rebuild(self): if not self._build_volume._width or not self._build_volume._height or not self._build_volume._depth: return if not self._build_volume._engine_ready: return if not self._build_volume._volume_outline_color: theme = Application.getInstance().getTheme() self._build_volume._volume_outline_color = Color( *theme.getColor("volume_outline").getRgb()) self._build_volume._x_axis_color = Color( *theme.getColor("x_axis").getRgb()) self._build_volume._y_axis_color = Color( *theme.getColor("y_axis").getRgb()) self._build_volume._z_axis_color = Color( *theme.getColor("z_axis").getRgb()) self._build_volume._disallowed_area_color = Color( *theme.getColor("disallowed_area").getRgb()) self._build_volume._error_area_color = Color( *theme.getColor("error_area").getRgb()) ### START PATCH # Get a dict from the machine metadata optionally overriding the build volume # Note that CuraEngine is blissfully unaware of this; it is just what the user is shown in Cura limit_buildvolume = self._build_volume._global_container_stack.getMetaDataEntry( "limit_buildvolume", {}) if not isinstance(limit_buildvolume, dict): limit_buildvolume = {} min_w = limit_buildvolume.get("width", {}).get("minimum", -self._build_volume._width / 2) max_w = limit_buildvolume.get("width", {}).get("maximum", self._build_volume._width / 2) min_h = limit_buildvolume.get("height", {}).get("minimum", 0.0) max_h = limit_buildvolume.get("height", {}).get("maximum", self._build_volume._height) min_d = limit_buildvolume.get("depth", {}).get("minimum", -self._build_volume._depth / 2) max_d = limit_buildvolume.get("depth", {}).get("maximum", self._build_volume._depth / 2) ### END PATCH z_fight_distance = 0.2 # Distance between buildplate and disallowed area meshes to prevent z-fighting if self._build_volume._shape != "elliptic": # Outline 'cube' of the build volume mb = MeshBuilder() mb.addLine(Vector(min_w, min_h, min_d), Vector(max_w, min_h, min_d), color=self._build_volume._volume_outline_color) mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, max_h, min_d), color=self._build_volume._volume_outline_color) mb.addLine(Vector(min_w, max_h, min_d), Vector(max_w, max_h, min_d), color=self._build_volume._volume_outline_color) mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, max_h, min_d), color=self._build_volume._volume_outline_color) mb.addLine(Vector(min_w, min_h, max_d), Vector(max_w, min_h, max_d), color=self._build_volume._volume_outline_color) mb.addLine(Vector(min_w, min_h, max_d), Vector(min_w, max_h, max_d), color=self._build_volume._volume_outline_color) mb.addLine(Vector(min_w, max_h, max_d), Vector(max_w, max_h, max_d), color=self._build_volume._volume_outline_color) mb.addLine(Vector(max_w, min_h, max_d), Vector(max_w, max_h, max_d), color=self._build_volume._volume_outline_color) mb.addLine(Vector(min_w, min_h, min_d), Vector(min_w, min_h, max_d), color=self._build_volume._volume_outline_color) mb.addLine(Vector(max_w, min_h, min_d), Vector(max_w, min_h, max_d), color=self._build_volume._volume_outline_color) mb.addLine(Vector(min_w, max_h, min_d), Vector(min_w, max_h, max_d), color=self._build_volume._volume_outline_color) mb.addLine(Vector(max_w, max_h, min_d), Vector(max_w, max_h, max_d), color=self._build_volume._volume_outline_color) self._build_volume.setMeshData(mb.build()) # Build plate grid mesh mb = MeshBuilder() mb.addQuad(Vector(min_w, min_h - z_fight_distance, min_d), Vector(max_w, min_h - z_fight_distance, min_d), Vector(max_w, min_h - z_fight_distance, max_d), Vector(min_w, min_h - z_fight_distance, max_d)) for n in range(0, 6): v = mb.getVertex(n) mb.setVertexUVCoordinates(n, v[0], v[2]) self._build_volume._grid_mesh = mb.build() else: # Bottom and top 'ellipse' of the build volume aspect = 1.0 scale_matrix = Matrix() if self._build_volume._width != 0: # Scale circular meshes by aspect ratio if width != height aspect = self._build_volume._depth / self._build_volume._width scale_matrix.compose(scale=Vector(1, 1, aspect)) mb = MeshBuilder() mb.addArc(max_w, Vector.Unit_Y, center=(0, min_h - z_fight_distance, 0), color=self._build_volume._volume_outline_color) mb.addArc(max_w, Vector.Unit_Y, center=(0, max_h, 0), color=self._build_volume._volume_outline_color) self._build_volume.setMeshData( mb.build().getTransformed(scale_matrix)) # Build plate grid mesh mb = MeshBuilder() mb.addVertex(0, min_h - z_fight_distance, 0) mb.addArc(max_w, Vector.Unit_Y, center=Vector(0, min_h - z_fight_distance, 0)) sections = mb.getVertexCount( ) - 1 # Center point is not an arc section indices = [] for n in range(0, sections - 1): indices.append([0, n + 2, n + 1]) mb.addIndices(numpy.asarray(indices, dtype=numpy.int32)) mb.calculateNormals() for n in range(0, mb.getVertexCount()): v = mb.getVertex(n) mb.setVertexUVCoordinates(n, v[0], v[2] * aspect) self._build_volume._grid_mesh = mb.build().getTransformed( scale_matrix) # Indication of the machine origin if self._build_volume._global_container_stack.getProperty( "machine_center_is_zero", "value"): origin = (Vector(min_w, min_h, min_d) + Vector(max_w, min_h, max_d)) / 2 else: origin = Vector(min_w, min_h, max_d) mb = MeshBuilder() mb.addCube(width=self._build_volume._origin_line_length, height=self._build_volume._origin_line_width, depth=self._build_volume._origin_line_width, center=origin + Vector(self._build_volume._origin_line_length / 2, 0, 0), color=self._build_volume._x_axis_color) mb.addCube(width=self._build_volume._origin_line_width, height=self._build_volume._origin_line_length, depth=self._build_volume._origin_line_width, center=origin + Vector(0, self._build_volume._origin_line_length / 2, 0), color=self._build_volume._y_axis_color) mb.addCube(width=self._build_volume._origin_line_width, height=self._build_volume._origin_line_width, depth=self._build_volume._origin_line_length, center=origin - Vector(0, 0, self._build_volume._origin_line_length / 2), color=self._build_volume._z_axis_color) self._build_volume._origin_mesh = mb.build() disallowed_area_height = 0.1 disallowed_area_size = 0 if self._build_volume._disallowed_areas: mb = MeshBuilder() color = self._build_volume._disallowed_area_color for polygon in self._build_volume._disallowed_areas: points = polygon.getPoints() if len(points) == 0: continue first = Vector( self._build_volume._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._build_volume._clamp(points[0][1], min_d, max_d)) previous_point = Vector( self._build_volume._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._build_volume._clamp(points[0][1], min_d, max_d)) for point in points: new_point = Vector( self._build_volume._clamp(point[0], min_w, max_w), disallowed_area_height, self._build_volume._clamp(point[1], min_d, max_d)) mb.addFace(first, previous_point, new_point, color=color) previous_point = new_point # Find the largest disallowed area to exclude it from the maximum scale bounds. # This is a very nasty hack. This pretty much only works for UM machines. # This disallowed area_size needs a -lot- of rework at some point in the future: TODO if numpy.min( points[:, 1] ) >= 0: # This filters out all areas that have points to the left of the centre. This is done to filter the skirt area. size = abs( numpy.max(points[:, 1]) - numpy.min(points[:, 1])) else: size = 0 disallowed_area_size = max(size, disallowed_area_size) self._build_volume._disallowed_area_mesh = mb.build() else: self._build_volume._disallowed_area_mesh = None if self._build_volume._error_areas: mb = MeshBuilder() for error_area in self._build_volume._error_areas: color = self._build_volume._error_area_color points = error_area.getPoints() first = Vector( self._build_volume._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._build_volume._clamp(points[0][1], min_d, max_d)) previous_point = Vector( self._build_volume._clamp(points[0][0], min_w, max_w), disallowed_area_height, self._build_volume._clamp(points[0][1], min_d, max_d)) for point in points: new_point = Vector( self._build_volume._clamp(point[0], min_w, max_w), disallowed_area_height, self._build_volume._clamp(point[1], min_d, max_d)) mb.addFace(first, previous_point, new_point, color=color) previous_point = new_point self._build_volume._error_mesh = mb.build() else: self._build_volume._error_mesh = None self._build_volume._volume_aabb = AxisAlignedBox( minimum=Vector(min_w, min_h - 1.0, min_d), maximum=Vector( max_w, max_h - self._build_volume._raft_thickness - self._build_volume._extra_z_clearance, max_d)) bed_adhesion_size = self._build_volume.getEdgeDisallowedSize() # As this works better for UM machines, we only add the disallowed_area_size for the z direction. # This is probably wrong in all other cases. TODO! # The +1 and -1 is added as there is always a bit of extra room required to work properly. scale_to_max_bounds = AxisAlignedBox( minimum=Vector( min_w + bed_adhesion_size + 1, min_h, min_d + disallowed_area_size - bed_adhesion_size + 1), maximum=Vector( max_w - bed_adhesion_size - 1, max_h - self._build_volume._raft_thickness - self._build_volume._extra_z_clearance, max_d - disallowed_area_size + bed_adhesion_size - 1)) Application.getInstance().getController().getScene( )._maximum_bounds = scale_to_max_bounds self._build_volume.updateNodeBoundaryCheck()