LayerDataBuilder.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. # Copyright (c) 2015 Ultimaker B.V.
  2. # Cura is released under the terms of the LGPLv3 or higher.
  3. from .Layer import Layer
  4. from .LayerPolygon import LayerPolygon
  5. from UM.Mesh.MeshBuilder import MeshBuilder
  6. from .LayerData import LayerData
  7. import numpy
  8. from typing import Dict, Optional
  9. class LayerDataBuilder(MeshBuilder):
  10. """Builder class for constructing a :py:class:`cura.LayerData.LayerData` object"""
  11. def __init__(self) -> None:
  12. super().__init__()
  13. self._layers = {} # type: Dict[int, Layer]
  14. self._element_counts = {} # type: Dict[int, int]
  15. def addLayer(self, layer: int) -> None:
  16. if layer not in self._layers:
  17. self._layers[layer] = Layer(layer)
  18. def getLayer(self, layer: int) -> Optional[Layer]:
  19. return self._layers.get(layer)
  20. def getLayers(self) -> Dict[int, Layer]:
  21. return self._layers
  22. def getElementCounts(self) -> Dict[int, int]:
  23. return self._element_counts
  24. def setLayerHeight(self, layer: int, height: float) -> None:
  25. if layer not in self._layers:
  26. self.addLayer(layer)
  27. self._layers[layer].setHeight(height)
  28. def setLayerThickness(self, layer: int, thickness: float) -> None:
  29. if layer not in self._layers:
  30. self.addLayer(layer)
  31. self._layers[layer].setThickness(thickness)
  32. def build(self, material_color_map, line_type_brightness = 1.0):
  33. """Return the layer data as :py:class:`cura.LayerData.LayerData`.
  34. :param material_color_map: [r, g, b, a] for each extruder row.
  35. :param line_type_brightness: compatibility layer view uses line type brightness of 0.5
  36. """
  37. vertex_count = 0
  38. index_count = 0
  39. for layer, data in self._layers.items():
  40. vertex_count += data.lineMeshVertexCount()
  41. index_count += data.lineMeshElementCount()
  42. vertices = numpy.empty((vertex_count, 3), numpy.float32)
  43. line_dimensions = numpy.empty((vertex_count, 2), numpy.float32)
  44. colors = numpy.empty((vertex_count, 4), numpy.float32)
  45. indices = numpy.empty((index_count, 2), numpy.int32)
  46. feedrates = numpy.empty((vertex_count), numpy.float32)
  47. extruders = numpy.empty((vertex_count), numpy.float32)
  48. line_types = numpy.empty((vertex_count), numpy.float32)
  49. vertex_indices = numpy.arange(0, vertex_count, 1, dtype = numpy.float32)
  50. vertex_offset = 0
  51. index_offset = 0
  52. for layer, data in sorted(self._layers.items()):
  53. vertex_offset, index_offset = data.build(vertex_offset, index_offset, vertices, colors, line_dimensions, feedrates, extruders, line_types, indices)
  54. self._element_counts[layer] = data.elementCount
  55. self.addVertices(vertices)
  56. colors[:, 0:3] *= line_type_brightness
  57. self.addColors(colors)
  58. self.addIndices(indices.flatten())
  59. # Note: we're using numpy indexing here.
  60. # See also: https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
  61. material_colors = numpy.zeros((line_dimensions.shape[0], 4), dtype=numpy.float32)
  62. for extruder_nr in range(material_color_map.shape[0]):
  63. material_colors[extruders == extruder_nr] = material_color_map[extruder_nr]
  64. # Set material_colors with indices where line_types (also numpy array) == MoveCombingType
  65. material_colors[line_types == LayerPolygon.MoveCombingType] = colors[line_types == LayerPolygon.MoveCombingType]
  66. material_colors[line_types == LayerPolygon.MoveRetractionType] = colors[line_types == LayerPolygon.MoveRetractionType]
  67. attributes = {
  68. "line_dimensions": {
  69. "value": line_dimensions,
  70. "opengl_name": "a_line_dim",
  71. "opengl_type": "vector2f"
  72. },
  73. "extruders": {
  74. "value": extruders,
  75. "opengl_name": "a_extruder",
  76. "opengl_type": "float" # Strangely enough, the type has to be float while it is actually an int.
  77. },
  78. "colors": {
  79. "value": material_colors,
  80. "opengl_name": "a_material_color",
  81. "opengl_type": "vector4f"
  82. },
  83. "line_types": {
  84. "value": line_types,
  85. "opengl_name": "a_line_type",
  86. "opengl_type": "float"
  87. },
  88. "feedrates": {
  89. "value": feedrates,
  90. "opengl_name": "a_feedrate",
  91. "opengl_type": "float"
  92. },
  93. # Can't use glDrawElements to index (due to oversight in (Py)Qt), can't use gl_PrimitiveID (due to legacy support):
  94. "vertex_indices": {
  95. "value": vertex_indices,
  96. "opengl_name": "a_vertex_index",
  97. "opengl_type": "float"
  98. }
  99. }
  100. return LayerData(vertices=self.getVertices(), normals=self.getNormals(), indices=self.getIndices(),
  101. colors=self.getColors(), uvs=self.getUVCoordinates(), file_name=self.getFileName(),
  102. center_position=self.getCenterPosition(), layers=self._layers,
  103. element_counts=self._element_counts, attributes=attributes)