def _rotateCamera(self, x, y): camera = self._scene.getActiveCamera() if not camera or not camera.isEnabled(): return self._scene.acquireLock() dx = math.radians(x * 180.0) dy = math.radians(y * 180.0) diff = camera.getPosition() - self._origin my = Matrix() my.setByRotationAxis(dx, Vector.Unit_Y) mx = Matrix(my.getData()) mx.rotateByAxis(dy, Vector.Unit_Y.cross(diff).normalize()) n = diff.multiply(mx) try: angle = math.acos(Vector.Unit_Y.dot(n.getNormalized())) except ValueError: return if angle < 0.1 or angle > math.pi - 0.1: n = diff.multiply(my) n += self._origin camera.setPosition(n) camera.lookAt(self._origin) self._scene.releaseLock()
def test_preMultiply(self): temp_matrix = Matrix() temp_matrix.setByTranslation(Vector(10,10,10)) temp_matrix2 = Matrix() temp_matrix2.setByScaleFactor(0.5) temp_matrix.preMultiply(temp_matrix2) numpy.testing.assert_array_almost_equal(temp_matrix.getData(), numpy.array([[0.5,0,0,5],[0,0.5,0,5],[0,0,0.5,5],[0,0,0,1]]))
def _updateTransformation(self): scale, shear, euler_angles, translation, mirror = self._transformation.decompose( ) self._position = translation self._scale = scale self._shear = shear self._mirror = mirror orientation = Quaternion() euler_angle_matrix = Matrix() euler_angle_matrix.setByEuler(euler_angles.x, euler_angles.y, euler_angles.z) orientation.setByMatrix(euler_angle_matrix) self._orientation = orientation if self._parent: self._world_transformation = self._parent.getWorldTransformation( ).multiply(self._transformation, copy=True) else: self._world_transformation = self._transformation world_scale, world_shear, world_euler_angles, world_translation, world_mirror = self._world_transformation.decompose( ) self._derived_position = world_translation self._derived_scale = world_scale world_euler_angle_matrix = Matrix() world_euler_angle_matrix.setByEuler(world_euler_angles.x, world_euler_angles.y, world_euler_angles.z) self._derived_orientation.setByMatrix(world_euler_angle_matrix)
def _createMatrixFromTransformationString(self, transformation): if transformation == "": return Matrix() splitted_transformation = transformation.split() ## Transformation is saved as: ## M00 M01 M02 0.0 ## M10 M11 M12 0.0 ## M20 M21 M22 0.0 ## 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] return temp_mat
def _transformCoordinates(self, x: float, y: float, z: float, i: float, j: float, k: float, position: Position) -> (float, float, float, float, float, float): a = position.a c = position.c # Get coordinate angles if abs(self._position.c - k) > 0.00001: a = math.acos(k) self._rot_nwp = Matrix() self._rot_nwp.setByRotationAxis(-a, Vector.Unit_X) a = degrees(a) if abs(self._position.a - i) > 0.00001 or abs(self._position.b - j) > 0.00001: c = numpy.arctan2(j, i) if x != 0 and y != 0 else 0 angle = degrees(c + self._pi_faction * 2 * math.pi) if abs(angle - position.c) > 180: self._pi_faction += 1 if (angle - position.c) < 0 else -1 c += self._pi_faction * 2 * math.pi c -= math.pi / 2 self._rot_nws = Matrix() self._rot_nws.setByRotationAxis(c, Vector.Unit_Z) c = degrees(c) #tr = self._rot_nws.multiply(self._rot_nwp, True) tr = self._rot_nws.multiply(self._rot_nwp, True) #tr = tr.multiply(self._rot_nwp) tr.invert() pt = Vector(data=numpy.array([x, y, z, 1])) ret = tr.multiply(pt, True).getData() return Position(ret[0], ret[1], ret[2], a, 0, c, 0, [0])
def processTransform(self, node): rot = readRotation(node, "rotation", (0, 0, 1, 0)) # (angle, axisVactor) tuple trans = readVector(node, "translation", (0, 0, 0)) # Vector scale = readVector(node, "scale", (1, 1, 1)) # Vector center = readVector(node, "center", (0, 0, 0)) # Vector scale_orient = readRotation(node, "scaleOrientation", (0, 0, 1, 0)) # (angle, axisVactor) tuple # Store the previous transform; in Cura, the default matrix multiplication is in place prev = Matrix(self.transform.getData()) # It's deep copy, I've checked # The rest of transform manipulation will be applied in place got_center = (center.x != 0 or center.y != 0 or center.z != 0) T = self.transform if trans.x != 0 or trans.y != 0 or trans.z !=0: T.translate(trans) if got_center: T.translate(center) if rot[0] != 0: T.rotateByAxis(*rot) if scale.x != 1 or scale.y != 1 or scale.z != 1: got_scale_orient = scale_orient[0] != 0 if got_scale_orient: T.rotateByAxis(*scale_orient) # No scale by vector in place operation in UM S = Matrix() S.setByScaleVector(scale) T.multiply(S) if got_scale_orient: T.rotateByAxis(-scale_orient[0], scale_orient[1]) if got_center: T.translate(-center) self.processChildNodes(node) self.transform = prev
def _rotateCamera(self, x: float, y: float) -> None: """Rotate the camera in response to a mouse event. :param x: Amount by which the camera should be rotated horizontally, expressed in pixelunits :param y: Amount by which the camera should be rotated vertically, expressed in pixelunits """ camera = self._scene.getActiveCamera() if not camera or not camera.isEnabled(): return dx = math.radians(x * 180.0) dy = math.radians(y * 180.0) diff = camera.getPosition() - self._origin my = Matrix() my.setByRotationAxis(dx, Vector.Unit_Y) mx = Matrix(my.getData()) mx.rotateByAxis(dy, Vector.Unit_Y.cross(diff).normalized()) n = diff.multiply(mx) try: angle = math.acos(Vector.Unit_Y.dot(n.normalized())) except ValueError: return if angle < 0.1 or angle > math.pi - 0.1: n = diff.multiply(my) n += self._origin camera.setPosition(n) camera.lookAt(self._origin)
def test_render(): mocked_shader = MagicMock() with patch("UM.View.GL.OpenGL.OpenGL.getInstance"): render_batch = RenderBatch(mocked_shader) # Render without a camera shouldn't cause any effect. render_batch.render(None) assert mocked_shader.bind.call_count == 0 # Rendering with a camera should cause the shader to be bound and released (even if the batch is empty) mocked_camera = MagicMock() mocked_camera.getWorldTransformation = MagicMock(return_value=Matrix()) mocked_camera.getViewProjectionMatrix = MagicMock(return_value=Matrix()) with patch("UM.View.GL.OpenGLContext.OpenGLContext.properties"): render_batch.render(mocked_camera) assert mocked_shader.bind.call_count == 1 assert mocked_shader.release.call_count == 1 # Actualy render with an item in the batch mb = MeshBuilder() mb.addPyramid(10, 10, 10, color=Color(0.0, 1.0, 0.0, 1.0)) mb.calculateNormals() mesh_data = mb.build() render_batch.addItem(Matrix(), mesh_data, {}) with patch("UM.View.GL.OpenGL.OpenGL.getInstance"): with patch("UM.View.GL.OpenGLContext.OpenGLContext.properties"): render_batch.render(mocked_camera) assert mocked_shader.bind.call_count == 2 assert mocked_shader.release.call_count == 2
def read(self, file_name): result = [] # The base object of 3mf is a zipped archive. try: archive = zipfile.ZipFile(file_name, "r") self._base_name = os.path.basename(file_name) parser = Savitar.ThreeMFParser() scene_3mf = parser.parse(archive.open("3D/3dmodel.model").read()) self._unit = scene_3mf.getUnit() for node in scene_3mf.getSceneNodes(): um_node = self._convertSavitarNodeToUMNode(node) if um_node is None: continue # compensate for original center position, if object(s) is/are not around its zero position transform_matrix = Matrix() mesh_data = um_node.getMeshData() if mesh_data is not None: extents = mesh_data.getExtents() center_vector = Vector(extents.center.x, extents.center.y, extents.center.z) transform_matrix.setByTranslation(center_vector) transform_matrix.multiply(um_node.getLocalTransformation()) um_node.setTransformation(transform_matrix) global_container_stack = Application.getInstance().getGlobalContainerStack() # Create a transformation Matrix to convert from 3mf worldspace into ours. # First step: flip the y and z axis. transformation_matrix = Matrix() transformation_matrix._data[1, 1] = 0 transformation_matrix._data[1, 2] = 1 transformation_matrix._data[2, 1] = -1 transformation_matrix._data[2, 2] = 0 # Second step: 3MF defines the left corner of the machine as center, whereas cura uses the center of the # build volume. if global_container_stack: translation_vector = Vector(x=-global_container_stack.getProperty("machine_width", "value") / 2, y=-global_container_stack.getProperty("machine_depth", "value") / 2, z=0) translation_matrix = Matrix() translation_matrix.setByTranslation(translation_vector) transformation_matrix.multiply(translation_matrix) # Third step: 3MF also defines a unit, wheras Cura always assumes mm. scale_matrix = Matrix() scale_matrix.setByScaleVector(self._getScaleFromUnit(self._unit)) transformation_matrix.multiply(scale_matrix) # Pre multiply the transformation with the loaded transformation, so the data is handled correctly. um_node.setTransformation(um_node.getLocalTransformation().preMultiply(transformation_matrix)) result.append(um_node) except Exception: Logger.logException("e", "An exception occurred in 3mf reader.") return [] return result
def test_compare(self): matrix = Matrix() matrix2 = Matrix() assert matrix == matrix assert not matrix == "zomg" matrix._data = None matrix2._data = None assert matrix == matrix2
def _createPolygon(self, layer_thickness: float, path: List[List[Union[float, int]]], extruder_offsets: List[float]) -> bool: countvalid = 0 for point in path: if point[8] > 0: countvalid += 1 if countvalid >= 2: # we know what to do now, no need to count further continue if countvalid < 2: return False try: self._layer_data_builder.addLayer(self._layer_number) self._layer_data_builder.setLayerHeight(self._layer_number, path[0][2]) self._layer_data_builder.setLayerThickness(self._layer_number, layer_thickness) this_layer = self._layer_data_builder.getLayer(self._layer_number) except ValueError: return False count = len(path) line_types = numpy.empty((count - 1, 1), numpy.int32) line_widths = numpy.empty((count - 1, 1), numpy.float32) line_thicknesses = numpy.empty((count - 1, 1), numpy.float32) line_feedrates = numpy.empty((count - 1, 1), numpy.float32) line_widths[:, 0] = 0.35 # Just a guess line_thicknesses[:, 0] = layer_thickness points = numpy.empty((count, 6), numpy.float32) extrusion_values = numpy.empty((count, 1), numpy.float32) i = 0 for point in path: matrix = Matrix([[point[0], point[1], point[2], 1]]) vector_matrix = Matrix([[0,0,1,1]]) matrix.rotateByAxis(radians(point[3]), Vector.Unit_X) matrix.rotateByAxis(radians(point[4]), Vector.Unit_Y) matrix.rotateByAxis(radians(point[5]), Vector.Unit_Z) vector_matrix.rotateByAxis(radians(point[3]), Vector.Unit_X) vector_matrix.rotateByAxis(radians(point[4]), Vector.Unit_Y) vector_matrix.rotateByAxis(radians(point[5]), Vector.Unit_Z) #points[i, :] = [point[0] + extruder_offsets[0], point[2], -point[1] - extruder_offsets[1]] points[i, :] = [matrix.at(0,0) + extruder_offsets[0], matrix.at(0,2), -matrix.at(0,1)-extruder_offsets[1], -vector_matrix.at(0,1), vector_matrix.at(0,2), -vector_matrix.at(0,0)] extrusion_values[i] = point[7] if i > 0: line_feedrates[i - 1] = point[6] line_types[i - 1] = point[8] if point[8] in [LayerPolygon.MoveCombingType, LayerPolygon.MoveRetractionType]: line_widths[i - 1] = 0.1 line_thicknesses[i - 1] = 0.0 # Travels are set as zero thickness lines else: line_widths[i - 1] = self._calculateLineWidth(points[i], points[i-1], extrusion_values[i], extrusion_values[i-1], layer_thickness) i += 1 this_poly = LayerPolygon(self._extruder_number, line_types, points, line_widths, line_thicknesses, line_feedrates) this_poly.buildCache() this_layer.polygons.append(this_poly) return True
def __init__(self, parent: Optional["SceneNode"] = None, visible: bool = True, name: str = "") -> None: super().__init__() # Call super to make multiple inheritance work. self._children = [] # type: List[SceneNode] self._mesh_data = None # type: Optional[MeshData] # Local transformation (from parent to local) self._transformation = Matrix() # type: Matrix # Convenience "components" of the transformation self._position = Vector() # type: Vector self._scale = Vector(1.0, 1.0, 1.0) # type: Vector self._shear = Vector(0.0, 0.0, 0.0) # type: Vector self._mirror = Vector(1.0, 1.0, 1.0) # type: Vector self._orientation = Quaternion() # type: Quaternion # World transformation (from root to local) self._world_transformation = Matrix() # type: Matrix # Convenience "components" of the world_transformation self._derived_position = Vector() # type: Vector self._derived_orientation = Quaternion() # type: Quaternion self._derived_scale = Vector() # type: Vector self._parent = parent # type: Optional[SceneNode] # Can this SceneNode be modified in any way? self._enabled = True # type: bool # Can this SceneNode be selected in any way? self._selectable = False # type: bool # Should the AxisAlignedBoundingBox be re-calculated? self._calculate_aabb = False # type: bool # The AxisAligned bounding box. self._aabb = None # type: Optional[AxisAlignedBox] self._bounding_box_mesh = None # type: Optional[MeshData] self._visible = visible # type: bool self._name = name # type: str self._decorators = [] # type: List[SceneNodeDecorator] # Store custom settings to be compatible with Savitar SceneNode self._settings = {} #type: Dict[str, Any] ## Signals self.boundingBoxChanged.connect(self.calculateBoundingBoxMesh) self.parentChanged.connect(self._onParentChanged) if parent: parent.addChild(self)
def test_preMultiplyCopy(self): temp_matrix = Matrix() temp_matrix.setByTranslation(Vector(10, 10, 10)) temp_matrix2 = Matrix() temp_matrix2.setByScaleFactor(0.5) result = temp_matrix.preMultiply(temp_matrix2, copy=True) assert result != temp_matrix numpy.testing.assert_array_almost_equal( result.getData(), numpy.array([[0.5, 0, 0, 5], [0, 0.5, 0, 5], [0, 0, 0.5, 5], [0, 0, 0, 1]]))
def addArc(self, **kwargs): radius = kwargs["radius"] axis = kwargs["axis"] max_angle = kwargs.get("angle", math.pi * 2) center = kwargs.get("center", Vector(0, 0, 0)) sections = kwargs.get("sections", 32) color = kwargs.get("color", None) if axis == Vector.Unit_Y: start = axis.cross(Vector.Unit_X).normalize() * radius else: start = axis.cross(Vector.Unit_Y).normalize() * radius angle_increment = max_angle / sections angle = 0 point = start + center m = Matrix() while angle <= max_angle: self._mesh_data.addVertex(point.x, point.y, point.z) angle += angle_increment m.setByRotationAxis(angle, axis) point = start.multiply(m) + center self._mesh_data.addVertex(point.x, point.y, point.z) if color: self._mesh_data.setVertexColor(self._mesh_data.getVertexCount() - 2, color) self._mesh_data.setVertexColor(self._mesh_data.getVertexCount() - 1, color)
def test_getterAndSetters(camera): # Pretty much all of them are super simple, but it doesn't hurt to check them. camera.setAutoAdjustViewPort(False) assert camera.getAutoAdjustViewPort() == False camera.setViewportWidth(12) assert camera.getViewportWidth() == 12 camera.setViewportHeight(12) assert camera.getViewportHeight() == 12 camera.setViewportSize(22, 22) assert camera.getViewportHeight() == 22 assert camera.getViewportWidth() == 22 camera.setWindowSize(9001, 9002) assert camera.getWindowSize() == (9001, 9002) camera.setPerspective(False) assert camera.isPerspective() == False matrix = Matrix() matrix.setPerspective(10, 20, 30, 40) camera.setProjectionMatrix(matrix) assert numpy.array_equal(camera.getProjectionMatrix().getData(), matrix.getData()) camera.setZoomFactor(1) assert camera.getZoomFactor() == 1 assert camera.render(None) # Should always be true, as it's a camera
def __init__(self, name: str = "", parent: Optional[SceneNode.SceneNode] = None) -> None: super().__init__(parent) self._name = name # type: str self._projection_matrix = Matrix() # type: Matrix self._projection_matrix.setOrtho(-5, 5, -5, 5, -100, 100) self._perspective = True # type: bool self._viewport_width = 0 # type: int self._viewport_height = 0 # type: int self._window_width = 0 # type: int self._window_height = 0 # type: int self._auto_adjust_view_port_size = True # type: bool self.setCalculateBoundingBox(False) self._cached_view_projection_matrix = None # type: Optional[Matrix] self._zoom_factor = Camera.getDefaultZoomFactor() from UM.Application import Application Application.getInstance().getPreferences().addPreference( "general/camera_perspective_mode", default_value=self.PerspectiveMode.PERSPECTIVE.value) Application.getInstance().getPreferences().preferenceChanged.connect( self._preferencesChanged) self._preferencesChanged("general/camera_perspective_mode")
def renderFullScreenQuad(self, shader: "ShaderProgram") -> None: """Render a full screen quad (rectangle). The function is used to draw render results on. :param shader: The shader to use when rendering. """ self._gl.glDisable(self._gl.GL_DEPTH_TEST) self._gl.glDisable(self._gl.GL_BLEND) shader.setUniformValue("u_modelViewProjectionMatrix", Matrix()) if OpenGLContext.properties["supportsVertexArrayObjects"]: vao = QOpenGLVertexArrayObject() vao.create() vao.bind() self._quad_buffer.bind() shader.enableAttribute("a_vertex", "vector3f", 0) shader.enableAttribute("a_uvs", "vector2f", 72) self._gl.glDrawArrays(self._gl.GL_TRIANGLES, 0, 6) shader.disableAttribute("a_vertex") shader.disableAttribute("a_uvs") self._quad_buffer.release()
def createSteps(self) -> pywim.WimList: steps = pywim.WimList(pywim.chop.model.Step) step = pywim.chop.model.Step(name='step-1') normal_mesh = getPrintableNodes()[0] cura_to_print = Matrix() cura_to_print._data[1, 1] = 0 cura_to_print._data[1, 2] = -1 cura_to_print._data[2, 1] = 1 cura_to_print._data[2, 2] = 0 mesh_transformation = normal_mesh.getLocalTransformation() mesh_transformation.preMultiply(cura_to_print) _, mesh_rotation, _, _ = mesh_transformation.decompose() # Add boundary conditions from the selected faces in the Smart Slice node for bc_node in DepthFirstIterator(self): if hasattr(bc_node, 'pywimBoundaryCondition'): bc = bc_node.pywimBoundaryCondition(step, mesh_rotation) steps.add(step) return steps
def scale(self, scale: Vector, transform_space: int = TransformSpace.Local) -> None: """Scale the scene object (and thus its children) by given amount :param scale: :type{Vector} A Vector with three scale values :param transform_space: The space relative to which to scale. Can be any one of the constants in SceneNode::TransformSpace. """ if not self._enabled: return scale_matrix = Matrix() scale_matrix.setByScaleVector(scale) if transform_space == SceneNode.TransformSpace.Local: self._transformation.multiply(scale_matrix) elif transform_space == SceneNode.TransformSpace.Parent: self._transformation.preMultiply(scale_matrix) elif transform_space == SceneNode.TransformSpace.World: self._transformation.multiply( self._world_transformation.getInverse()) self._transformation.multiply(scale_matrix) self._transformation.multiply(self._world_transformation) self._transformChanged()
def setCenterPosition(self, center: Vector) -> None: if self._mesh_data: m = Matrix() m.setByTranslation(-center) self._mesh_data = self._mesh_data.getTransformed(m).set(center_position=center) for child in self._children: child.setCenterPosition(center)
def _rotateCameraFree(angle: float, axisX: float, axisY: float, axisZ: float) -> None: if SpaceMouseTool._rotationLocked: return camera = SpaceMouseTool._scene.getActiveCamera() if not camera or not camera.isEnabled(): return # compute axis in view space: # space mouse system: x: right, y: front, z: down # camera system: x: right, y: up, z: front # i.e. rotate the vector about x by 90 degrees in mathematical positive sense axisInViewSpace = np.array([-axisX, axisZ, -axisY, 1]) # get inverse view matrix invViewMatrix = camera.getWorldTransformation().getData() # compute rotation axis in world space axisInWorldSpace = homogenize(np.dot(invViewMatrix, axisInViewSpace)) originInWorldSpace = homogenize( np.dot(invViewMatrix, np.array([0, 0, 0, 1]))) axisInWorldSpace = axisInWorldSpace - originInWorldSpace axisInWorldSpace = Vector(data=axisInWorldSpace) # rotate camera around that axis by angle rotOrigin = SpaceMouseTool._cameraTool.getOrigin() # rotation matrix around the axis rotMat = Matrix() rotMat.setByRotationAxis(angle, axisInWorldSpace, rotOrigin.getData()) camera.setTransformation( camera.getLocalTransformation().preMultiply(rotMat))
def addArc(self, radius, axis, angle=math.pi * 2, center=Vector(0, 0, 0), sections=32, color=None): #We'll compute the vertices of the arc by computing an initial point and #rotating the initial point with a rotation matrix. if axis == Vector.Unit_Y: start = axis.cross(Vector.Unit_X).normalized() * radius else: start = axis.cross(Vector.Unit_Y).normalized() * radius angle_increment = angle / sections current_angle = 0 point = start + center m = Matrix() while current_angle <= angle: #Add each of the vertices. self.addVertex(point.x, point.y, point.z) current_angle += angle_increment m.setByRotationAxis(current_angle, axis) point = start.multiply( m ) + center #Get the next vertex by rotating the start position with a matrix. self.addVertex(point.x, point.y, point.z) if color: #If we have a colour, add that colour to the new vertex. self.setVertexColor(self.getVertexCount() - 2, color) self.setVertexColor(self.getVertexCount() - 1, color)
def _setUniformValueDirect(self, uniform, value): if type(value) is Vector: self._shader_program.setUniformValue( uniform, QVector3D(value.x, value.y, value.z)) elif type(value) is Matrix: self._shader_program.setUniformValue( uniform, self._matrixToQMatrix4x4(value)) elif type(value) is Color: self._shader_program.setUniformValue( uniform, QColor(value.r * 255, value.g * 255, value.b * 255, value.a * 255)) elif type(value) is list and type(value[0]) is list and len( value[0]) == 4: self._shader_program.setUniformValue( uniform, self._matrixToQMatrix4x4(Matrix(value))) elif type(value) is list and len(value) == 2: self._shader_program.setUniformValue(uniform, QVector2D(value[0], value[1])) elif type(value) is list and len(value) == 3: self._shader_program.setUniformValue( uniform, QVector3D(value[0], value[1], value[2])) elif type(value) is list and len(value) == 4: self._shader_program.setUniformValue( uniform, QVector4D(value[0], value[1], value[2], value[3])) elif type(value) is list and type(value[0]) is list and len( value[0]) == 2: self._shader_program.setUniformValueArray( uniform, [QVector2D(i[0], i[1]) for i in value]) else: self._shader_program.setUniformValue(uniform, value)
def __init__(self, node, translation = None, orientation = None, scale = None, shear = None, mirror = None): super().__init__() self._node = node self._old_translation = node.getPosition() self._old_orientation = node.getOrientation() self._old_scale = node.getScale() self._old_shear = node.getShear() self._old_transformation = node.getWorldTransformation() if translation: self._new_translation = translation else: self._new_translation = node.getPosition() if orientation: self._new_orientation = orientation else: self._new_orientation = node.getOrientation() if scale: self._new_scale = scale else: self._new_scale = node.getScale() if shear: self._new_shear = shear else: self._new_shear = node.getShear() self._new_mirror = Vector(1, 1, 1) self._new_transformation = Matrix() euler_orientation = self._new_orientation.toMatrix().getEuler() self._new_transformation.compose(scale = self._new_scale, shear = self._new_shear, angles = euler_orientation, translate = self._new_translation, mirror = self._new_mirror)
def bakeMeshTransformation(self) -> None: nodes_list = self._getSelectedNodes() if not nodes_list: return op = GroupedOperation() for node in nodes_list: mesh_data = node.getMeshData() if not mesh_data: continue mesh_name = node.getName() if not mesh_name: file_name = mesh_data.getFileName() if not file_name: file_name = "" mesh_name = os.path.basename(file_name) if not mesh_name: mesh_name = catalog.i18nc("@text Print job name", "Untitled") local_transformation = node.getLocalTransformation() position = local_transformation.getTranslation() local_transformation.setTranslation(Vector(0,0,0)) transformed_mesh_data = mesh_data.getTransformed(local_transformation) new_transformation = Matrix() new_transformation.setTranslation(position) op.addOperation(SetMeshDataAndNameOperation(node, transformed_mesh_data, mesh_name)) op.addOperation(SetTransformMatrixOperation(node, new_transformation)) op.push()
def readerRead(self, reader, file_name, **kwargs): try: results = reader.read(file_name) if results is not None: if type(results) is not list: results = [results] for result in results: if kwargs.get("center", True): # If the result has a mesh and no children it needs to be centered if result.getMeshData() and len( result.getChildren()) == 0: extents = result.getMeshData().getExtents() move_vector = Vector(extents.center.x, extents.center.y, extents.center.z) result.setCenterPosition(move_vector) # Move all the meshes of children so that toolhandles are shown in the correct place. for node in result.getChildren(): if node.getMeshData(): extents = node.getMeshData().getExtents() m = Matrix() m.translate(-extents.center) node.setMeshData( node.getMeshData().getTransformed(m)) node.translate(extents.center) return results except OSError as e: Logger.log("e", str(e)) Logger.log("w", "Unable to read file %s", file_name) return None # unable to read
def setOrientation(self, orientation: Quaternion, transform_space: int = TransformSpace.Local): if not self._enabled or orientation == self._orientation: return new_transform_matrix = Matrix() if transform_space == SceneNode.TransformSpace.World: if self.getWorldOrientation() == orientation: return new_orientation = orientation * ( self.getWorldOrientation() * self._orientation.getInverse()).getInverse() orientation_matrix = new_orientation.toMatrix() else: # Local orientation_matrix = orientation.toMatrix() euler_angles = orientation_matrix.getEuler() new_transform_matrix.compose(scale=self._scale, angles=euler_angles, translate=self._position, shear=self._shear) self._transformation = new_transform_matrix self._transformChanged()
def _updateCachedNormalMatrix(self) -> None: self._cached_normal_matrix = Matrix( self.getWorldTransformation(copy=False).getData()) self._cached_normal_matrix.setRow(3, [0, 0, 0, 1]) self._cached_normal_matrix.setColumn(3, [0, 0, 0, 1]) self._cached_normal_matrix.pseudoinvert() self._cached_normal_matrix.transpose()
def test_toMatrix(self): q1 = Quaternion() q1.setByAngleAxis(math.pi / 2, Vector.Unit_Z) m1 = q1.toMatrix() m2 = Matrix() m2.setByRotationAxis(math.pi / 2, Vector.Unit_Z) self.assertTrue(Float.fuzzyCompare(m1.at(0, 0), m2.at(0, 0), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(0, 1), m2.at(0, 1), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(0, 2), m2.at(0, 2), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(0, 3), m2.at(0, 3), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(1, 0), m2.at(1, 0), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(1, 1), m2.at(1, 1), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(1, 2), m2.at(1, 2), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(1, 3), m2.at(1, 3), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(2, 0), m2.at(2, 0), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(2, 1), m2.at(2, 1), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(2, 2), m2.at(2, 2), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(2, 3), m2.at(2, 3), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(3, 0), m2.at(3, 0), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(3, 1), m2.at(3, 1), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(3, 2), m2.at(3, 2), 1e-6)) self.assertTrue(Float.fuzzyCompare(m1.at(3, 3), m2.at(3, 3), 1e-6))
def setOrientation(self, orientation: Quaternion, transform_space: int = TransformSpace.Local) -> None: """Set the local orientation of this scene node. :param orientation: :type{Quaternion} The new orientation of this scene node. :param transform_space: The space relative to which to rotate. Can be Local or World from SceneNode::TransformSpace. """ if not self._enabled or orientation == self._orientation: return if transform_space == SceneNode.TransformSpace.World: if self.getWorldOrientation() == orientation: return new_orientation = orientation * ( self.getWorldOrientation() * self._orientation.getInverse()).invert() orientation_matrix = new_orientation.toMatrix() else: # Local orientation_matrix = orientation.toMatrix() euler_angles = orientation_matrix.getEuler() new_transform_matrix = Matrix() new_transform_matrix.compose(scale=self._scale, angles=euler_angles, translate=self._position, shear=self._shear) self._transformation = new_transform_matrix self._transformChanged()