예제 #1
0
파일: CameraTool.py 프로젝트: jf---/Uranium
    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()
예제 #2
0
 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]]))
예제 #3
0
    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)
예제 #4
0
    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
예제 #5
0
 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])
예제 #6
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
예제 #7
0
    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)
예제 #8
0
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
예제 #9
0
    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
예제 #10
0
    def test_compare(self):
        matrix = Matrix()
        matrix2 = Matrix()

        assert matrix == matrix
        assert not matrix == "zomg"

        matrix._data = None
        matrix2._data = None
        assert matrix == matrix2
예제 #11
0
    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
예제 #12
0
    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)
예제 #13
0
 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]]))
예제 #14
0
    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)
예제 #15
0
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
예제 #16
0
파일: Camera.py 프로젝트: greatnam/Uranium
    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")
예제 #17
0
    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()
예제 #18
0
    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
예제 #19
0
    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()
예제 #20
0
 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))
예제 #22
0
    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)
예제 #23
0
 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)
예제 #25
0
    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()
예제 #26
0
    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
예제 #27
0
    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()
예제 #28
0
 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()
예제 #29
0
    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))
예제 #30
0
    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()