Ejemplo n.º 1
0
    def test_invert(self):
        q1 = Quaternion()
        q1.setByAngleAxis(math.pi, Vector.Unit_Z)

        q1.invert()

        q2 = Quaternion()
        q2.setByAngleAxis(math.pi, -Vector.Unit_Z)

        self.assertEqual(q1, q2)
Ejemplo n.º 2
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)
Ejemplo n.º 3
0
    def test_multiply(self):
        q1 = Quaternion()
        q1.setByAngleAxis(math.pi / 2, Vector.Unit_Z)

        q2 = Quaternion()
        q2.setByAngleAxis(math.pi / 2, Vector.Unit_Z)

        q3 = q1 * q2

        q4 = Quaternion()
        q4.setByAngleAxis(math.pi, Vector.Unit_Z)
        self.assertEqual(q3, q4)
Ejemplo n.º 4
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))
Ejemplo n.º 5
0
    def resetRotation(self):

        for node in Selection.getAllSelectedObjects():
            node.setMirror(Vector(1, 1, 1))

        Selection.applyOperation(SetTransformOperation, None, Quaternion(),
                                 None)
Ejemplo n.º 6
0
    def resetAll(self):
        Logger.log("i", "Resetting all scene transformations")
        nodes = []
        for node in DepthFirstIterator(
                self.getController().getScene().getRoot()):
            if type(node) is not SceneNode:
                continue
            if not node.getMeshData() and not node.callDecoration("isGroup"):
                continue  # Node that doesnt have a mesh and is not a group.
            if node.getParent() and node.getParent().callDecoration("isGroup"):
                continue  # Grouped nodes don't need resetting as their parent (the group) is resetted)
            nodes.append(node)

        if nodes:
            op = GroupedOperation()
            for node in nodes:
                # Ensure that the object is above the build platform
                node.removeDecorator(ZOffsetDecorator.ZOffsetDecorator)
                center_y = 0
                if node.callDecoration("isGroup"):
                    center_y = node.getWorldPosition().y - node.getBoundingBox(
                    ).bottom
                else:
                    center_y = node.getMeshData().getCenterPosition().y
                op.addOperation(
                    SetTransformOperation(node, Vector(0, center_y, 0),
                                          Quaternion(), Vector(1, 1, 1)))
            op.push()
Ejemplo n.º 7
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)
Ejemplo n.º 8
0
    def test_create(self):
        q = Quaternion()

        self.assertEqual(q.x, 0.0)
        self.assertEqual(q.y, 0.0)
        self.assertEqual(q.z, 0.0)
        self.assertEqual(q.w, 1.0)
Ejemplo n.º 9
0
    def resetRotation(self):
        """Reset the orientation of the mesh(es) to their original orientation(s)"""

        for node in self._getSelectedObjectsWithoutSelectedAncestors():
            node.setMirror(Vector(1, 1, 1))

        Selection.applyOperation(SetTransformOperation, None, Quaternion(), None)
Ejemplo n.º 10
0
    def _updateTransformation(self):
        self._transformation = Matrix.fromPositionOrientationScale(
            self._position, self._orientation, self._scale)

        if self._parent:
            parent_orientation = self._parent._getDerivedOrientation()
            if self._inherit_orientation:
                self._derived_orientation = parent_orientation * self._orientation
            else:
                self._derived_orientation = self._orientation

            # Sometimes the derived orientation can be None.
            # I've not been able to locate the cause of this, but this prevents it being an issue.
            if not self._derived_orientation:
                self._derived_orientation = Quaternion()

            parent_scale = self._parent._getDerivedScale()
            if self._inherit_scale:
                self._derived_scale = parent_scale.scale(self._scale)
            else:
                self._derived_scale = self._scale

            self._derived_position = parent_orientation.rotate(
                parent_scale.scale(self._position))
            self._derived_position += self._parent._getDerivedPosition()

            self._world_transformation = Matrix.fromPositionOrientationScale(
                self._derived_position, self._derived_orientation,
                self._derived_scale)
        else:
            self._derived_position = self._position
            self._derived_orientation = self._orientation
            self._derived_scale = self._scale
            self._world_transformation = self._transformation
Ejemplo n.º 11
0
    def __init__(self, parent=None):
        super().__init__()  # Call super to make multiple inheritence work.

        self._children = []
        self._mesh_data = None

        self._position = Vector()
        self._scale = Vector(1.0, 1.0, 1.0)
        self._orientation = Quaternion()

        self._transformation = None
        self._world_transformation = None

        self._derived_position = None
        self._derived_orientation = None
        self._derived_scale = None

        self._inherit_orientation = True
        self._inherit_scale = True

        self._parent = parent
        self._enabled = True
        self._selectable = False
        self._calculate_aabb = True
        self._aabb = None
        self._aabb_job = None
        self._visible = True
        self._name = ""
        self._decorators = []
        self._bounding_box_mesh = None
        self.boundingBoxChanged.connect(self.calculateBoundingBoxMesh)
        self.parentChanged.connect(self._onParentChanged)

        if parent:
            parent.addChild(self)
Ejemplo n.º 12
0
    def resetAll(self):
        nodes = []
        for node in DepthFirstIterator(
                self.getController().getScene().getRoot()):
            if type(node) is not SceneNode:
                continue
            if not node.getMeshData() and not node.callDecoration("isGroup"):
                continue  #Node that doesnt have a mesh and is not a group.
            if node.getParent() and node.getParent().callDecoration("isGroup"):
                continue  #Grouped nodes don't need resetting as their parent (the group) is resetted)
            nodes.append(node)

        if nodes:
            op = GroupedOperation()

            for node in nodes:
                # Ensure that the object is above the build platform
                move_distance = node.getBoundingBox().center.y
                if move_distance <= 0:
                    move_distance = -node.getBoundingBox().bottom
                op.addOperation(
                    SetTransformOperation(node, Vector(0, move_distance, 0),
                                          Quaternion(), Vector(1, 1, 1)))

            op.push()
Ejemplo n.º 13
0
    def setZ(self, Z):
        if float(Z) != self._Z_angle:
            self._angle = ((float(Z) % 360) - (self._Z_angle % 360)) % 360

            self._Z_angle = float(Z)

            #rotation = Quaternion.fromAngleAxis(math.radians( self._angle ), Vector.Unit_Z)
            rotation = Quaternion()
            rotation.setByAngleAxis(math.radians(self._angle), Vector.Unit_Z)

            # Save the current positions of the node, as we want to rotate around their current centres
            self._saved_node_positions = []
            for node in Selection.getAllSelectedObjects():
                self._saved_node_positions.append((node, node.getPosition()))
                node._rotationZ = self._Z_angle

            # Rate-limit the angle change notification
            # This is done to prevent the UI from being flooded with property change notifications,
            # which in turn would trigger constant repaints.
            new_time = time.monotonic()
            if not self._angle_update_time or new_time - self._angle_update_time > 0.1:
                self._angle_update_time = new_time

                # Rotate around the saved centeres of all selected nodes
                op = GroupedOperation()
                for node, position in self._saved_node_positions:
                    op.addOperation(
                        RotateOperation(node,
                                        rotation,
                                        rotate_around_point=position))
                op.push()

            self._angle = 0
            self.propertyChanged.emit()
Ejemplo n.º 14
0
    def resetRotation(self):

        for node in self._getSelectedObjectsWithoutSelectedAncestors():
            node.setMirror(Vector(1, 1, 1))

        Selection.applyOperation(SetTransformOperation, None, Quaternion(),
                                 None)
Ejemplo n.º 15
0
    def test_getData(self):
        q = Quaternion(1, 2, 3, 4)

        data = q.getData()
        assert data[0] == 1
        assert data[1] == 2
        assert data[2] == 3
        assert data[3] == 4
Ejemplo n.º 16
0
    def _getDerivedOrientation(self):
        if not self._derived_orientation:
            self._updateTransformation()

        # Sometimes the derived orientation can be None.
        # I've not been able to locate the cause of this, but this prevents it being an issue.
        if not self._derived_orientation:
            self._derived_orientation = Quaternion()
        return self._derived_orientation
Ejemplo n.º 17
0
    def test_setByAxis(self):
        q = Quaternion()

        q.setByAngleAxis(math.pi / 2, Vector.Unit_Z)

        self.assertEqual(q.x, 0.0)
        self.assertEqual(q.y, 0.0)
        self.assertTrue(Float.fuzzyCompare(q.z, math.sqrt(2.0) / 2.0, 1e-6))
        self.assertTrue(Float.fuzzyCompare(q.w, math.sqrt(2.0) / 2.0, 1e-6))
Ejemplo n.º 18
0
    def _updateLocalTransformation(self):
        translation, euler_angle_matrix, scale, shear = self._transformation.decompose()

        self._position = translation
        self._scale = scale
        self._shear = shear
        orientation = Quaternion()
        orientation.setByMatrix(euler_angle_matrix)
        self._orientation = orientation
Ejemplo n.º 19
0
    def __init__(self, parent = None, **kwargs):
        super().__init__()  # Call super to make multiple inheritance work.

        self._children = []
        self._mesh_data = None

        # Local transformation (from parent to local)
        self._transformation = Matrix()

        # Convenience "components" of the transformation
        self._position = Vector()
        self._scale = Vector(1.0, 1.0, 1.0)
        self._shear = Vector(0.0, 0.0, 0.0)
        self._mirror = Vector(1.0, 1.0, 1.0)
        self._orientation = Quaternion()

        # World transformation (from root to local)
        self._world_transformation = Matrix()

        # Convenience "components" of the world_transformation
        self._derived_position = Vector()
        self._derived_orientation = Quaternion()
        self._derived_scale = Vector()

        self._parent = parent
        self._enabled = True  # Can this SceneNode be modified in any way?
        self._selectable = False  # Can this SceneNode be selected in any way?

        self._calculate_aabb = True  # Should the AxisAlignedBounxingBox be re-calculated?
        self._aabb = None  # The AxisAligned bounding box.
        self._original_aabb = None  # The AxisAligned bounding box, without transformations.
        self._bounding_box_mesh = None

        self._visible = kwargs.get("visible", True)
        self._name = kwargs.get("name", "")
        self._decorators = []

        ## Signals
        self.boundingBoxChanged.connect(self.calculateBoundingBoxMesh)
        self.parentChanged.connect(self._onParentChanged)

        if parent:
            parent.addChild(self)
Ejemplo n.º 20
0
    def test_rotateVector(self):
        q1 = Quaternion()
        q1.setByAngleAxis(math.pi / 2, Vector.Unit_Z)

        v = Vector(0, 1, 0)
        v = q1.rotate(v)

        self.assertTrue(Float.fuzzyCompare(v.x, -1.0, 1e-6))
        self.assertTrue(Float.fuzzyCompare(v.y, 0.0, 1e-6))
        self.assertTrue(Float.fuzzyCompare(v.z, 0.0, 1e-6))
Ejemplo n.º 21
0
    def updateFromODE(self):
        self._update_from_ode = True

        self.getNode().setPosition(Helpers.fromODE(self._body.getPosition()),
                                   SceneNode.TransformSpace.World)

        body_orientation = self._body.getQuaternion()
        self.getNode().setOrientation(
            Quaternion(body_orientation[3], body_orientation[0],
                       body_orientation[1], body_orientation[2]))

        self._update_from_ode = False
Ejemplo n.º 22
0
    def test_rotate(self):
        node = SceneNode()

        self.assertEqual(node.getOrientation(), Quaternion())

        node.rotate(Quaternion.fromAngleAxis(math.pi / 4, Vector.Unit_Z))

        self.assertEqual(node.getOrientation(), Quaternion.fromAngleAxis(math.pi / 4, Vector.Unit_Z))

        node.rotate(Quaternion.fromAngleAxis(math.pi / 4, Vector.Unit_Z))

        self.assertEqual(node.getOrientation(), Quaternion.fromAngleAxis(math.pi / 2, Vector.Unit_Z))
Ejemplo n.º 23
0
    def __init__(self, parent=None, **kwargs):
        super().__init__()  # Call super to make multiple inheritance work.

        self._children = []
        self._mesh_data = None

        # Local transformation (from parent to local)
        self._transformation = Matrix()

        # Convenience "components" of the transformation
        self._position = Vector()
        self._scale = Vector(1.0, 1.0, 1.0)
        self._shear = Vector(0.0, 0.0, 0.0)
        self._orientation = Quaternion()

        # World transformation (from root to local)
        self._world_transformation = Matrix()

        # Convenience "components" of the world_transformation
        self._derived_position = Vector()
        self._derived_orientation = Quaternion()
        self._derived_scale = Vector()

        self._parent = parent
        self._enabled = True
        self._selectable = False
        self._calculate_aabb = True
        self._aabb = None
        self._original_aabb = None
        self._aabb_job = None
        self._visible = kwargs.get("visible", True)
        self._name = kwargs.get("name", "")
        self._decorators = []

        ## Signals
        self.boundingBoxChanged.connect(self.calculateBoundingBoxMesh)
        self.parentChanged.connect(self._onParentChanged)

        if parent:
            parent.addChild(self)
Ejemplo n.º 24
0
    def test_fromMatrix(self):
        m = Matrix()
        m.setByRotationAxis(math.pi / 2, Vector.Unit_Z)

        q1 = Quaternion.fromMatrix(m)

        q2 = Quaternion()
        q2.setByAngleAxis(math.pi / 2, Vector.Unit_Z)

        self.assertTrue(Float.fuzzyCompare(q1.x, q2.x, 1e-6))
        self.assertTrue(Float.fuzzyCompare(q1.y, q2.y, 1e-6))
        self.assertTrue(Float.fuzzyCompare(q1.z, q2.z, 1e-6))
        self.assertTrue(Float.fuzzyCompare(q1.w, q2.w, 1e-6))
Ejemplo n.º 25
0
    def resetRotation(self):
        for node in Selection.getAllSelectedObjects():
            node.setMirror(Vector(1, 1, 1))
            node._rotationX = 0.0
            node._rotationY = 0.0
            node._rotationZ = 0.0

        Selection.applyOperation(SetTransformOperation, None, Quaternion(),
                                 None)

        self._X_angle = 0
        self._Z_angle = 0
        self._Y_angle = 0
        self.propertyChanged.emit()
Ejemplo n.º 26
0
    def resetAll(self):
        nodes = []
        for node in DepthFirstIterator(self.getController().getScene().getRoot()):
            if type(node) is not SceneNode or not node.getMeshData():
                continue
            nodes.append(node)

        if nodes:
            op = GroupedOperation()

            for node in nodes:
                op.addOperation(SetTransformOperation(node, Vector(), Quaternion(), Vector(1, 1, 1)))

            op.push()
Ejemplo n.º 27
0
    def test_rotate(self):
        node = SceneNode()

        self.assertEqual(node.getOrientation(), Quaternion())

        node.rotate(Quaternion.fromAngleAxis(math.pi / 4, Vector.Unit_Z))

        node_orientation = deepcopy(node.getOrientation())
        node_orientation.normalize()  #For fair comparison.
        self.assertEqual(node_orientation,
                         Quaternion.fromAngleAxis(math.pi / 4, Vector.Unit_Z))

        node.rotate(Quaternion.fromAngleAxis(math.pi / 4, Vector.Unit_Z))

        node_orientation = deepcopy(node.getOrientation())
        node_orientation.normalize()
        self.assertEqual(node_orientation,
                         Quaternion.fromAngleAxis(math.pi / 2, Vector.Unit_Z))
Ejemplo n.º 28
0
    def resetAll(self):
        nodes = []
        for node in DepthFirstIterator(
                self.getController().getScene().getRoot()):
            if type(node) is not SceneNode:
                continue
            if not node.getMeshData() and not node.callDecoration("isGroup"):
                continue  #Node that doesnt have a mesh and is not a group.
            if node.getParent() and node.getParent().callDecoration("isGroup"):
                continue  #Grouped nodes don't need resetting as their parent (the group) is resetted)
            nodes.append(node)

        if nodes:
            op = GroupedOperation()

            for node in nodes:
                op.addOperation(
                    SetTransformOperation(node, Vector(), Quaternion(),
                                          Vector(1, 1, 1)))

            op.push()
Ejemplo n.º 29
0
    def test_slerp(self):
        q1 = Quaternion()
        q1.setByAngleAxis(0, Vector.Unit_Z)

        q2 = Quaternion()
        q2.setByAngleAxis(math.pi / 2, Vector.Unit_Z)

        c = Quaternion(0.0, 0.0, 0.0, 1.0)
        self.assertEqual(c, Quaternion.slerp(q1, q2, 0.0))

        c = Quaternion(0.0, 0.0, 0.19509033858776093, 0.9807853102684021)
        self.assertEqual(c, Quaternion.slerp(q1, q2, 0.25))

        c = Quaternion(0.0, 0.0, 0.38268348574638367, 0.9238795638084412)
        self.assertEqual(c, Quaternion.slerp(q1, q2, 0.5))

        c = Quaternion(0.0, 0.0, 0.5555703043937683, 0.8314696550369263)
        self.assertEqual(c, Quaternion.slerp(q1, q2, 0.75))

        c = Quaternion(0.0, 0.0, 0.7071068286895752, 0.7071068286895752)
        self.assertEqual(c, Quaternion.slerp(q1, q2, 1.0))
Ejemplo n.º 30
0
 def resetRotation(self):
     Selection.applyOperation(SetTransformOperation, None, Quaternion(), None)