Esempio n. 1
0
class Scene( scene.Scene ):

    def __init__( self, core_profile = True ):
        super( Scene, self ).__init__( core_profile )

    @property
    def name( self ):
        return "Basic"

    def initialise( self ):
        super( Scene, self ).initialise()

        def set_gl_state():
            # setup our GL state
            # enable z buffer
            GL.glEnable( GL.GL_DEPTH_TEST )

            # enable back face culling
            GL.glEnable( GL.GL_CULL_FACE )
            GL.glCullFace( GL.GL_BACK )

        set_gl_state()

        # create a viewport
        # this will be updated before we begin
        self.viewport = None

        # create a cube to render
        self.cube = renderable_cube.create( self.core_profile )

        def setup_scene():
            # create a scene
            # we'll create the scene as a tree
            # to demonstrate the depth-first iteration
            # technique we will use to render it
            self.scene_root = SceneNode( 'root' )

            # the letter indicates the tier the node
            # is on, a = tier 1, b = tier 2, etc.
            self.a1 = SceneNode( 'a1' )
            self.b1 = SceneNode( 'b1' )
            self.b2 = SceneNode( 'b2' )
            self.c1 = SceneNode( 'c1' )
            self.c2 = SceneNode( 'c2' )
            self.c3 = SceneNode( 'c3' )

            # the tree looks as follows
            #                / c1
            #           / b1 - c2
            # root - a1
            #           \ b2 - c3
            self.scene_root.add_child( self.a1 )
            self.a1.add_child( self.b1 )
            self.a1.add_child( self.b2 )
            self.b1.add_child( self.c1 )
            self.b1.add_child( self.c2 )
            self.b2.add_child( self.c3 )

            # if we set the nodes local scale (transform)
            # it will be affected by the parent's scale.
            # by setting the world scale (world_transform)
            # we are ignoring the parent's scale.
            # re-attaching the node would invalidate this.
            self.a1.world_transform.scale = [2.0, 2.0, 2.0]
            self.b1.world_transform.scale = [1.0, 1.0, 1.0]
            self.b2.world_transform.scale = [1.0, 1.0, 1.0]
            self.c1.world_transform.scale = [0.8, 0.8, 0.8]
            self.c2.world_transform.scale = [0.8, 0.8, 0.8]
            self.c3.world_transform.scale = [0.8, 0.8, 0.8]

            # move our scene nodes
            # leave a1 at the centre
            self.b1.transform.object.translate( [10.0, 0.0, 0.0 ] )
            self.b2.transform.object.translate([-10.0, 0.0, 0.0 ] )
            self.c1.transform.object.translate( [ 5.0, 0.0, 0.0 ] )
            self.c2.transform.object.translate( [-5.0, 0.0, 0.0 ] )
            self.c3.transform.object.translate( [ 5.0, 0.0, 0.0 ] )

            # rotate the our b nodes so they tilting forward
            self.b1.transform.object.rotate_x( math.pi / 4.0 )
            self.b2.transform.object.rotate_x( math.pi / 4.0 )

        setup_scene()

        def setup_camera():
            # create our camera node
            self.camera = CameraNode( 'camera', pyrr.matrix44.create_identity() )
            self.scene_root.add_child( self.camera )

            # move the camera so we're not inside
            # the root scene node's debug cube
            self.camera.transform.object.translate(
                [ 0.0, 30.0, 35.0 ]
                )

            # tilt the camera downward
            self.camera.transform.object.rotate_x(-math.pi / 4.0 )

        setup_camera()

    def on_window_resized( self, width, height ):
        # update the viewport
        self.viewport = pyrr.rectangle.create_from_position(
            x = 0,
            y = 0,
            width = width,
            height = height
            )

        # update the projection matrix
        # we need to do this or the rendering will become skewed with each
        # resize of viewport change
        aspect_ratio = pyrr.rectangle.aspect_ratio( self.viewport )
        self.camera.projection_matrix = pyrr.matrix44.create_perspective_projection_matrix(
            fovy = 80.0,
            aspect = aspect_ratio,
            near = 1.0,
            far = 100.0
            )

    def step( self, dt ):
        super( Scene, self ).step( dt )

        # setup the scene
        # rotate the scene nodes about their vertical axis
        self.a1.transform.object.rotate_y( dt )
        self.b1.transform.object.rotate_y( dt )
        self.b2.transform.object.rotate_y( dt )
        self.c1.transform.object.rotate_y( dt )
        self.c2.transform.object.rotate_y( dt )
        self.c3.transform.object.rotate_y( dt )

    def render( self ):
        super( Scene, self ).render()

        # this code is split into 2 functions to support the
        # multiple_viewports scene which inherits from this class
        self.render_viewport( self.viewport, self.camera )

    def render_viewport( self, viewport, camera ):
        def render_core():
            projection = camera.projection_matrix
            model_view = camera.model_view

            for node in self.scene_root.dfs():
                if isinstance( node, CameraNode ):
                    continue

                # get the node's world matrix
                world_matrix = node.world_transform.matrix

                # apply the camera's model view to the node's matrix
                current_mv = pyrr.matrix44.multiply(
                    world_matrix,
                    model_view
                    )

                # render a cube
                self.cube.draw( projection, current_mv )

        def render_legacy():
            # load our projection matrix
            with pygly.gl.mode_and_matrix(
                GL.GL_PROJECTION,
                camera.projection_matrix
                ):
                with pygly.gl.mode_and_matrix(
                    GL.GL_MODELVIEW,
                    camera.model_view
                    ):
                    # iterate through the scene graph
                    for node in self.scene_root.dfs():
                        # don't render cameras
                        if isinstance( node, CameraNode ):
                            continue

                        world_matrix = node.world_transform.matrix

                        # multiply the existing model view matrix
                        # by the model's world matrix
                        # then render a cube
                        with pygly.gl.multiply_matrix( world_matrix ):
                            self.cube.draw()

        # activate our viewport
        pygly.viewport.set_viewport( viewport )

        # set our scissor to the main viewport
        pygly.viewport.set_scissor( viewport )

        # clear the colour and depth buffer
        GL.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT )

        # render the scene
        if self.core_profile:
            render_core()
        else:
            render_legacy()