def __init__(self):
        configuration = self.Configuration()
        configuration.title = "Magnum Python Primitives + SceneGraph Example"
        platform.Application.__init__(self, configuration)

        gl.Renderer.enable(gl.Renderer.Feature.DEPTH_TEST)
        gl.Renderer.enable(gl.Renderer.Feature.FACE_CULLING)

        # Scene and drawables
        self._scene = Scene3D()
        self._drawables = scenegraph.DrawableGroup3D()

        # Camera setup
        camera_object = Object3D(self._scene)
        camera_object.translate(Vector3.z_axis(10.0))
        self._camera = scenegraph.Camera3D(camera_object)
        self._camera.projection_matrix = Matrix4.perspective_projection(
            fov=Deg(35.0), aspect_ratio=1.33333, near=0.01, far=100.0)

        # Cube object and drawable
        self._cube = Object3D(self._scene)
        self._cube.rotate_y(Deg(40.0))
        self._cube.rotate_x(Deg(30.0))
        self._cube_drawable = CubeDrawable(
            self._cube, self._drawables,
            meshtools.compile(primitives.cube_solid()), shaders.Phong(),
            Color3.from_hsv(Deg(35.0), 1.0, 1.0))
예제 #2
0
    def test_transformation(self):
        scene = Scene3D()

        a = Object3D(scene)

        # like a.rotate_local(Deg(35.0), Vector3.x_axis()), but way uglier,
        # another could be scipy.spatial.transform.Rotation but that's meh as
        # well
        a.transform_local(
            np.array([[1.0, 0.0, 0.0, 0.0], [0.0, 0.819152, -0.573576, 0.0],
                      [0.0, 0.573576, 0.819152, 0.0], [0.0, 0.0, 0.0, 1.0]]))
        self.assertEqual(a.transformation, Matrix4.rotation_x(Deg(35.0)))
        self.assertEqual(a.absolute_transformation(),
                         Matrix4.rotation_x(Deg(35.0)))

        b = Object3D(a)
        b.translate(np.array([3.0, 4.0, 5.0], dtype='float32'))
        self.assertEqual(b.transformation, Matrix4.translation(
            (3.0, 4.0, 5.0)))
        self.assertEqual(
            b.absolute_transformation(),
            Matrix4.rotation_x(Deg(35.0)) @ Matrix4.translation(
                (3.0, 4.0, 5.0)))

        c = Object3D(scene)
        self.assertEqual(c.transformation, Matrix4.identity_init())
        self.assertEqual(c.absolute_transformation(), Matrix4.identity_init())
예제 #3
0
    def test_camera_draw(self):
        scene = Scene3D()
        drawables = scenegraph.DrawableGroup3D()

        camera_object = Object3D(scene)
        camera_object.translate((0.0, 1.0, 5.0))

        camera = scenegraph.Camera3D(camera_object)

        rendered = None, None
        deleted = "no :)"

        class MyDrawable(scenegraph.Drawable3D):
            def draw(self, transformation_matrix: Matrix4,
                     camera: scenegraph.Camera3D):
                nonlocal rendered
                rendered = (transformation_matrix, camera)

            def __del__(self):
                nonlocal deleted
                deleted = "yes :("

        class MySilentDrawable(scenegraph.Drawable3D):
            def draw(self, transformation_matrix: Matrix4,
                     camera: scenegraph.Camera3D):
                pass

        object = Object3D(scene)
        object.translate(Vector3.x_axis(5.0))
        a = MyDrawable(object, drawables)
        b = MySilentDrawable(object, drawables)

        # The drawable group should have these listed
        self.assertEqual([i for i in drawables], [a, b])

        # Deleting the object, the camera holder and drawable does nothing
        del camera_object, object, a, b

        camera.draw(drawables)
        self.assertEqual(
            rendered[0],
            Matrix4.translation(Vector3.x_axis(5.0)) @ Matrix4.translation(
                (0.0, -1.0, -5.0)))
        self.assertIs(rendered[1], camera)

        # Deleting the scene will delete A and the drawable as well
        del scene
        self.assertEqual(deleted, "yes :(")
        self.assertIsNone(camera.object)
        self.assertIs(len(drawables), 0)
예제 #4
0
    def __init__(self):
        configuration = self.Configuration()
        configuration.title = "Magnum Python Viewer Example"
        Application.__init__(self, configuration)

        gl.Renderer.enable(gl.Renderer.Feature.DEPTH_TEST)
        gl.Renderer.enable(gl.Renderer.Feature.FACE_CULLING)

        # Scene and drawables
        self._scene = Scene3D()
        self._drawables = scenegraph.DrawableGroup3D()

        # Every scene needs a camera
        camera_object = Object3D(parent=self._scene)
        camera_object.translate(Vector3.z_axis(5.0))
        self._camera = scenegraph.Camera3D(camera_object)
        self._camera.aspect_ratio_policy = scenegraph.AspectRatioPolicy.EXTEND
        self._camera.projection_matrix = Matrix4.perspective_projection(
            fov=Deg(35.0), aspect_ratio=1.0, near=0.01, far=100.0)
        self._camera.viewport = self.framebuffer_size

        # Base object, parent of all (for easy manipulation)
        self._manipulator = Object3D(parent=self._scene)

        # Setup renderer and shader defaults
        gl.Renderer.enable(gl.Renderer.Feature.DEPTH_TEST)
        gl.Renderer.enable(gl.Renderer.Feature.FACE_CULLING)
        colored_shader = shaders.Phong()
        colored_shader.ambient_color = Color3(0.06667)
        colored_shader.shininess = 80.0

        # Import Suzanne head and eyes (yes, sorry, it's all hardcoded here)
        importer = trade.ImporterManager().load_and_instantiate(
            'TinyGltfImporter')
        importer.open_file(
            os.path.join(os.path.dirname(__file__), '../viewer/scene.glb'))
        suzanne_object = Object3D(parent=self._manipulator)
        suzanne_mesh = meshtools.compile(
            importer.mesh(importer.mesh_for_name('Suzanne')))
        suzanne_eyes_mesh = meshtools.compile(
            importer.mesh(importer.mesh_for_name('Eyes')))
        self._suzanne = ColoredDrawable(suzanne_object, self._drawables,
                                        suzanne_mesh, colored_shader,
                                        Color3(0.15, 0.49, 1.0))
        self._suzanne_eyes = ColoredDrawable(suzanne_object, self._drawables,
                                             suzanne_eyes_mesh, colored_shader,
                                             Color3(0.95))

        self._previous_mouse_position = Vector2i()
예제 #5
0
    def test_camera(self):
        object = Object3D()
        object.translate(Vector3.z_axis(5.0))
        object_refcount = sys.getrefcount(object)

        a = scenegraph.Camera3D(object)
        a.viewport = (400, 300)
        a.projection_matrix = Matrix4.perspective_projection(fov=Deg(45.0),
                                                             near=0.01,
                                                             far=100.0,
                                                             aspect_ratio=1.0)
        a.aspect_ratio_policy = scenegraph.AspectRatioPolicy.EXTEND
        a_refcount = sys.getrefcount(a)
        self.assertEqual(a.viewport, Vector2i(400, 300))
        self.assertEqual(
            a.projection_matrix,
            Matrix4.perspective_projection(fov=Deg(57.82240),
                                           near=0.01,
                                           far=100.0,
                                           aspect_ratio=1.33333333))
        self.assertEqual(a.camera_matrix,
                         Matrix4.translation(-Vector3.z_axis(5.0)))
        self.assertEqual(a.aspect_ratio_policy,
                         scenegraph.AspectRatioPolicy.EXTEND)
        self.assertIs(a.object, object)

        # Camera should be referenced by the object, but not cyclically
        self.assertEqual(sys.getrefcount(object), object_refcount)
        self.assertEqual(sys.getrefcount(a), object_refcount + 1)

        # Delete the object. The camera should be still alive, but disconnected
        # from the object (and thus useless).
        del object
        self.assertIsNone(a.object)
        self.assertEqual(sys.getrefcount(a), a_refcount - 1)
예제 #6
0
    def test_drawable_group(self):
        object = Object3D()
        drawables = scenegraph.DrawableGroup3D()

        deleted = 0

        class MyDrawable(scenegraph.Drawable3D):
            def __del__(self):
                nonlocal deleted
                deleted += 1

        a = MyDrawable(object, drawables)
        b = MyDrawable(object, drawables)

        # The drawable group should have these listed
        self.assertEqual([i for i in drawables], [a, b])

        # Deleting each of them should do nothing, since they're still
        # referenced by the object
        del a, b
        self.assertEqual(deleted, 0)
        self.assertEqual(len(drawables), 2)

        # Deleting the holder object will, tho
        del object
        self.assertEqual(deleted, 2)
        self.assertEqual(len(drawables), 0)
예제 #7
0
    def test(self):
        class MyFeature(scenegraph.AbstractFeature3D):
            def __init__(self, object: Object3D):
                scenegraph.AbstractFeature3D.__init__(self, object)

        object = Object3D()
        feature = MyFeature(object)
        self.assertIs(feature.object, object)
    def test_transformation(self):
        scene = Scene3D()

        a = Object3D(scene)
        a.rotate_local(Deg(35.0), Vector3.x_axis())
        self.assertEqual(a.transformation, Matrix4.rotation_x(Deg(35.0)))
        self.assertEqual(a.absolute_transformation(), Matrix4.rotation_x(Deg(35.0)))

        b = Object3D(a)
        b.translate((3.0, 4.0, 5.0))
        self.assertEqual(b.transformation, Matrix4.translation((3.0, 4.0, 5.0)))
        self.assertEqual(b.absolute_transformation(),
            Matrix4.rotation_x(Deg(35.0))@
            Matrix4.translation((3.0, 4.0, 5.0)))

        c = Object3D(scene)
        self.assertEqual(c.transformation, Matrix4.identity_init())
        self.assertEqual(c.absolute_transformation(), Matrix4.identity_init())
예제 #9
0
    def test_hierarchy_set_parent(self):
        # Same as test_hierarchy, but setting the parent later

        scene = Scene3D()
        scene_refcount = sys.getrefcount(scene)

        a = Object3D()
        a_refcount = sys.getrefcount(a)
        self.assertIs(a.scene, None)

        b = Object3D()
        b.parent = scene
        b_refcount = sys.getrefcount(b)
        self.assertIs(b.scene, scene)
        self.assertIs(b.parent, scene)

        # B should be referenced by the scene, but not cyclically
        self.assertEqual(sys.getrefcount(b), scene_refcount + 1)
        self.assertEqual(sys.getrefcount(scene), scene_refcount)

        c = Object3D()
        c.parent = b
        c_refcount = sys.getrefcount(c)
        self.assertIs(c.scene, scene)
        self.assertIs(c.parent, b)

        # C should be referenced by B
        self.assertEqual(sys.getrefcount(b), scene_refcount + 1)
        self.assertEqual(sys.getrefcount(c), scene_refcount + 1)
        self.assertEqual(sys.getrefcount(scene), scene_refcount)

        # Delete B. Because B has a parent as well, it's not deleted yet
        del b
        self.assertIsNotNone(c.parent)
        self.assertEqual(sys.getrefcount(c.parent), b_refcount - 1)
        self.assertEqual(sys.getrefcount(c), scene_refcount + 1)

        # Delete a scene. That also makes B deleted and C is then orphaned
        del scene
        self.assertIsNone(c.parent)
        self.assertEqual(sys.getrefcount(c), c_refcount - 1)
예제 #10
0
    def test_drawable(self):
        object = Object3D()
        object_refcount = sys.getrefcount(object)

        a = scenegraph.Drawable3D(object)
        a_refcount = sys.getrefcount(a)
        self.assertIs(a.object, object)

        b = scenegraph.Drawable3D(object)
        b_refcount = sys.getrefcount(b)
        self.assertIs(b.object, object)

        # Drawables should be referenced by the object, but not cyclically
        self.assertEqual(sys.getrefcount(object), object_refcount)
        self.assertEqual(sys.getrefcount(a), object_refcount + 1)
        self.assertEqual(sys.getrefcount(b), object_refcount + 1)

        # Delete the object. The drawable should be still alive, but
        # disconnected from the object (and thus useless).
        del object
        self.assertIsNone(a.object)
        self.assertIsNone(b.object)
        self.assertEqual(sys.getrefcount(a), a_refcount - 1)
        self.assertEqual(sys.getrefcount(b), b_refcount - 1)
예제 #11
0
 def test_set_parent_invalid(self):
     a = Object3D()
     with self.assertRaisesRegex(
             TypeError,
             "expected Scene, Object or None, got <class 'str'>"):
         a.parent = "noo"