Ejemplo n.º 1
0
    def set_and_draw(self):
        """Setup the camera and draw"""

        # reset everything
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        self.pick_reset()
        self.shader_set()

        # skybox
        self.shader_set(self.shader_skybox)
        self.set_modelview_matrix(
            Mat4.rotate(math.radians(self.phi),   1, 0, 0) @
            Mat4.rotate(math.radians(self.theta), 0, 0, 1)
        )
        glDisable(GL_DEPTH_TEST)
        self.skybox.draw()
        glEnable(GL_DEPTH_TEST)
        self.shader_set()

        # set up camera
        self.set_modelview_matrix(
            Mat4.translate(0, 0, -1/self.zoom) @
            Mat4.rotate(math.radians(self.phi),   1, 0, 0) @
            Mat4.rotate(math.radians(self.theta), 0, 0, 1)
        )

        self.draw()
        self.clear_pick_object()
Ejemplo n.º 2
0
    def draw(self):
        """Draw the scene"""
        self.set_color(1, 1, 1, 1)
        self.add_pick_object("the sphere")
        glutSolidSphere(1, 16, 16)

        transform = self.modelview_matrix

        transform @= Mat4.translate(-4, -4, 0)
        self.set_modelview_matrix(transform)
        self.set_color(1, 0, 0, 1)
        self.add_pick_object("the cube")
        glutSolidCube(2)

        transform @= Mat4.translate(0, 8, 0)
        self.set_modelview_matrix(transform)
        self.set_color(1, 1, 0, 1)
        self.add_pick_object("the torus")
        glutSolidTorus(1, 2, 16, 16)

        transform @= Mat4.translate(8, 0, 0)
        self.set_modelview_matrix(transform)
        self.set_color(0, 0, 1, 1)
        self.add_pick_object("the cone")
        glutSolidCone(1, 2, 16, 16)

        transform @= Mat4.translate(0, -8, 0) @ Mat4.scale(.5, .5, .5)
        self.set_modelview_matrix(transform)
        self.set_color(0, 1, 1, 1)
        self.add_pick_object("the dodecahedron")
        glutSolidDodecahedron()
Ejemplo n.º 3
0
    def draw(self):
        """Draw the scene"""
        self.set_color(1, 1, 1, 1)
        self.add_pick_object("the sphere")
        glutSolidSphere(1, 16, 16)

        transform = self.modelview_matrix

        transform @= Mat4.translate(-4, -4, 0)
        self.set_modelview_matrix(transform)
        self.set_color(1, 0, 0, 1)
        self.add_pick_object("the cube")
        glutSolidCube(2)

        transform @= Mat4.translate(0, 8, 0)
        self.set_modelview_matrix(transform)
        self.set_color(1, 1, 0, 1)
        self.add_pick_object("the torus")
        glutSolidTorus(1, 2, 16, 16)

        transform @= Mat4.translate(8, 0, 0)
        self.set_modelview_matrix(transform)
        self.set_color(0, 0, 1, 1)
        self.add_pick_object("the cone")
        glutSolidCone(1, 2, 16, 16)

        transform @= Mat4.translate(0, -8, 0) @ Mat4.scale(.5, .5, .5)
        self.set_modelview_matrix(transform)
        self.set_color(0, 1, 1, 1)
        self.add_pick_object("the dodecahedron")
        glutSolidDodecahedron()
Ejemplo n.º 4
0
    def set_and_draw(self):
        """Setup the camera and draw"""

        # reset everything
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        self.pick_reset()
        self.shader_set()

        # skybox
        self.shader_set(self.shader_skybox)
        self.set_modelview_matrix(
            Mat4.rotate(math.radians(self.phi), 1, 0, 0) @ Mat4.rotate(
                math.radians(self.theta), 0, 0, 1))
        glDisable(GL_DEPTH_TEST)
        self.skybox.draw()
        glEnable(GL_DEPTH_TEST)
        self.shader_set()

        # set up camera
        self.set_modelview_matrix(
            Mat4.translate(0, 0, -1 / self.zoom) @ Mat4.rotate(
                math.radians(self.phi), 1, 0, 0) @ Mat4.rotate(
                    math.radians(self.theta), 0, 0, 1))

        self.draw()
        self.clear_pick_object()
Ejemplo n.º 5
0
    def __init__(self, title=b'Scene'):
        # default settings
        self.zoom = .25
        self.drag_active = False
        self.mouse_x = 0
        self.mouse_y = 0
        self.theta = 0
        self.phi = -90
        self.is_running = True  # set to False for soft exit

        # GLUT init
        glutInit(sys.argv)
        glutInitContextVersion(3, 0)  # 2.0 enough, 3.0 = forward compatiblity
        glutInitContextFlags(GLUT_FORWARD_COMPATIBLE | GLUT_DEBUG)
        glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH
                            | GLUT_MULTISAMPLE)
        glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE,
                      GLUT_ACTION_GLUTMAINLOOP_RETURNS)
        glutInitWindowSize(1024, 768)
        glutCreateWindow(title)
        self.fullscreen = False

        # callbacks
        glutDisplayFunc(self.displayFunc)
        glutKeyboardFunc(self.keyboardFunc)
        glutSpecialFunc(self.specialFunc)
        glutReshapeFunc(self.reshapeFunc)
        glutMotionFunc(self.motionFunc)
        glutPassiveMotionFunc(self.passiveMotionFunc)
        glutMouseFunc(self.mouseFunc)
        glutCloseFunc(self.closeFunc)

        # OpenGL init
        glEnable(GL_CULL_FACE)  # one-way faces
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_BLEND)
        glEnable(GL_MULTISAMPLE)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
        glClearColor(0.0, 0.0, 0.0, 1.0)

        # use of VAO is required by OpenGL 3.2 core, so we use one if available
        if bool(glGenVertexArrays):  # OpenGL 3.0
            vao = glGenVertexArrays(1)
            glEnableVertexAttribArray(vao)
            glBindVertexArray(vao)

        # initialize textures
        gspyce.textures.init()

        # shader management
        program = main_program()
        self.default_shader = program
        self.current_shader = program
        glUseProgram(program)
        self.modelview_matrix = Mat4()
        self.projection_matrix = Mat4()
        self.set_color(1., 1., 1., 1.)
Ejemplo n.º 6
0
 def __init__(self, orbit):
     self.orbit = orbit
     self.transform = (
         Mat4.rotate(orbit.longitude_of_ascending_node, 0, 0, 1) @
         Mat4.rotate(orbit.inclination,                 1, 0, 0) @
         Mat4.rotate(orbit.argument_of_periapsis,       0, 0, 1) @
         Mat4.translate(-orbit.focus, 0, 0) @
         Mat4.scale(orbit.semi_major_axis, orbit.semi_minor_axis, 1.0)
     )
     super().__init__(GL_POINTS)
Ejemplo n.º 7
0
    def draw(self):
        """Draw the scene"""
        self.set_modelview_matrix(
            self.modelview_matrix @
            Mat4.rotate(radians(90), 1, 0, 0) @
            # fixed-pipeline transforms in glutWireTeapot() (freeglut_teapot.c)
            Mat4.rotate(radians(270.0), 1, 0, 0) @
            Mat4.scale(.5, .5, .5) @
            Mat4.translate(0, 0, -1.5)
        )

        glutWireTeapot(1)
Ejemplo n.º 8
0
    def vertices(self):
        orbit = self.orbit

        # now, we fix the three issues mentioned above
        # draw the orbit from the body rather than from the orbit focus (1.)

        if orbit.eccentricity >= 1.:  # open orbits
            # choose interpolation points
            def _():
                true_anomaly = orbit.true_anomaly_at_time(self.time)
                # decide when to stop drawing
                max_true_anomaly = orbit.true_anomaly_at_escape()
                if max_true_anomaly is None:
                    max_true_anomaly = orbit.ejection_angle() - 1e-2
                # normal hyperbola
                n = 128
                for i in range(n+1):
                    t = 2.*i/n - 1
                    yield max_true_anomaly * t
                # ensure the body will be on the line (2.)
                # more points close to the camera (3.)
                n = 64
                for i in range(n+1):
                    t = 2.*i/n - 1
                    theta = true_anomaly + t * abs(t)
                    if abs(theta) < max_true_anomaly:
                        yield theta
            angles = sorted(_())

            focus_offset = orbit.position_at_time(self.time)
            for angle in angles:
                yield orbit.position_at_true_anomaly(angle) - focus_offset
        else:  # closed orbits
            # nice hack with circle symetry to draw the orbit from the body
            # while still using VBOs
            # unsure it can be adapted for parabolic and hyperbolic orbits

            # make tilted ellipse from a circle; and rotate at current anomaly
            anomaly = orbit.eccentric_anomaly_at_time(self.time)
            transform = (
                Mat4.rotate(orbit.longitude_of_ascending_node, 0, 0, 1) @
                Mat4.rotate(orbit.inclination,                 1, 0, 0) @
                Mat4.rotate(orbit.argument_of_periapsis,       0, 0, 1) @
                Mat4.scale(orbit.semi_major_axis, orbit.semi_minor_axis, 1.0) @
                Mat4.rotate(anomaly - math.pi, 0, 0, 1)
            )

            # the first point of circle_through_origin is (0,0) (2.)
            # more points are located near the origin (3.)
            base_mesh = CircleThroughOrigin(1, 256)
            for vertice in base_mesh.vertices():
                yield transform @ Vec4(*vertice)
Ejemplo n.º 9
0
    def set_and_draw_hud(self):
        """Set up the camera and draw the HUD"""

        # save matrix state
        original_projection_matrix = self.projection_matrix
        original_modelview_matrix = self.modelview_matrix

        # set up matrices for HUD
        transform = Mat4.ortho(0.0, self.width, self.height, 0.0, -1.0, 10.0)
        self.set_projection_matrix(transform)
        self.set_modelview_matrix(Mat4())

        # reset HUD
        self.texcoords = []
        self.vertcoords = []
        self.hud_grid(0, 1)

        # fill vertex lists
        self.draw_hud()

        program = self.current_shader

        # vertices
        var = glGetAttribLocation(program, "vertex")
        glEnableVertexAttribArray(var)
        self.text_vbo.fill(self.vertcoords)
        self.text_vbo.bind()
        glVertexAttribPointer(var, 2, GL_FLOAT, False, 0, None)
        self.text_vbo.unbind()

        # textures coordinates
        var = glGetAttribLocation(program, "texcoord")
        glEnableVertexAttribArray(var)
        self.text_tbo.fill(self.texcoords)
        self.text_tbo.bind()
        glVertexAttribPointer(var, 2, GL_FLOAT, False, 0, None)
        self.text_tbo.unbind()

        # actually draw
        self.set_color(1, 1, 1, 1)
        glBindTexture(GL_TEXTURE_2D, self.font)
        glDrawArrays(GL_TRIANGLES, 0, self.text_vbo.size // 2)
        glBindTexture(GL_TEXTURE_2D, 0)

        # restore state
        var = glGetAttribLocation(program, "texcoord")
        glDisableVertexAttribArray(var)
        var = glGetAttribLocation(program, "vertex")
        glDisableVertexAttribArray(var)
        self.set_modelview_matrix(original_modelview_matrix)
        self.set_projection_matrix(original_projection_matrix)
Ejemplo n.º 10
0
    def set_and_draw(self):
        """Setup the camera and draw"""

        # reset everything
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        self.shader_set()

        # set camera
        self.set_modelview_matrix(
            Mat4.translate(0, 0, -1 / self.zoom) @ Mat4.rotate(
                radians(self.phi), 1, 0, 0) @ Mat4.rotate(
                    radians(self.theta), 0, 0, 1))

        # draw!
        self.draw()
Ejemplo n.º 11
0
 def vertices(self):
     orbit = self.orbit
     transform = (
         Mat4.rotate(orbit.longitude_of_ascending_node, 0, 0, 1) @
         Mat4.rotate(orbit.inclination,                 1, 0, 0) @
         Mat4.rotate(orbit.argument_of_periapsis,       0, 0, 1) @
         Mat4.translate(-orbit.focus, 0, 0) @
         Mat4.scale(orbit.semi_major_axis, orbit.semi_minor_axis, 1.0)
     )
     if orbit.eccentricity < 1.:
         base_mesh = Circle(1, 512)
     else:
         base_mesh = Parabola(256)
     for vertice in base_mesh.vertices():
         yield transform @ Vec4(*vertice)
Ejemplo n.º 12
0
    def set_and_draw(self):
        """Setup the camera and draw"""

        # reset everything
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        self.shader_set()

        # set camera
        self.set_modelview_matrix(
            Mat4.translate(0, 0, -1/self.zoom) @
            Mat4.rotate(radians(self.phi),   1, 0, 0) @
            Mat4.rotate(radians(self.theta), 0, 0, 1)
        )

        # draw!
        self.draw()
Ejemplo n.º 13
0
    def draw_body(self, body):
        """Draw a CelestialBody"""

        transform = (
            self.modelview_matrix @
            Mat4.translate(*body._relative_position)
        )
        self.add_pick_object(body)

        # axial tilt
        if body.north_pole is not None:
            z_angle = body.north_pole.ecliptic_longitude - math.pi/2
            transform @= Mat4.rotate(z_angle, 0, 0, 1)
            x_angle = body.north_pole.ecliptic_latitude - math.pi/2
            transform @= Mat4.rotate(x_angle, 1, 0, 0)

        # OpenGL use single precision while Python has double precision
        # reducing modulo 2 PI in Python reduces loss of significance
        turn_fraction, _ = math.modf(self.time / body.rotational_period)
        transform @= Mat4.rotate(2 * math.pi * turn_fraction, 0, 0, 1)

        # radius
        transform @= Mat4.scale(body.radius, body.radius, body.radius)

        # textured quadric (representation from close by)
        # sphere with radius proportional to that of the body
        if body.texture:
            glBindTexture(GL_TEXTURE_2D, body.texture)
        else:
            original_color = self.color
            self.set_color(.5, .5, 1., 1.)

        original_modelview_matrix = self.modelview_matrix
        self.set_modelview_matrix(transform)
        self.sphere.draw()
        self.set_modelview_matrix(original_modelview_matrix)

        if body.texture:
            glBindTexture(GL_TEXTURE_2D, 0)
        else:
            self.set_color(*original_color)

        glDepthMask(True)
Ejemplo n.º 14
0
    def draw_body(self, body):
        """Draw a CelestialBody"""

        transform = (
            self.modelview_matrix @ Mat4.translate(*body._relative_position))
        self.add_pick_object(body)

        # axial tilt
        if body.north_pole is not None:
            z_angle = body.north_pole.ecliptic_longitude - math.pi / 2
            transform @= Mat4.rotate(z_angle, 0, 0, 1)
            x_angle = body.north_pole.ecliptic_latitude - math.pi / 2
            transform @= Mat4.rotate(x_angle, 1, 0, 0)

        # OpenGL use single precision while Python has double precision
        # reducing modulo 2 PI in Python reduces loss of significance
        turn_fraction, _ = math.modf(self.time / body.rotational_period)
        transform @= Mat4.rotate(2 * math.pi * turn_fraction, 0, 0, 1)

        # radius
        transform @= Mat4.scale(body.radius, body.radius, body.radius)

        # textured quadric (representation from close by)
        # sphere with radius proportional to that of the body
        if body.texture:
            glBindTexture(GL_TEXTURE_2D, body.texture)
        else:
            original_color = self.color
            self.set_color(.5, .5, 1., 1.)

        original_modelview_matrix = self.modelview_matrix
        self.set_modelview_matrix(transform)
        self.sphere.draw()
        self.set_modelview_matrix(original_modelview_matrix)

        if body.texture:
            glBindTexture(GL_TEXTURE_2D, 0)
        else:
            self.set_color(*original_color)

        glDepthMask(True)
Ejemplo n.º 15
0
    def reshapeFunc(self, width, height):
        """Handle window reshapings (GLUT callback)"""
        glViewport(0, 0, width, height)
        self.width = width
        self.height = height

        aspect = height / width
        near = .1
        # see https://stackoverflow.com/a/16459424/4457767
        self.set_projection_matrix(
            Mat4.frustrum(-near, near, -near * aspect, near * aspect, 2 * near,
                          1e7))
Ejemplo n.º 16
0
    def reshapeFunc(self, width, height):
        """Handle window reshapings (GLUT callback)"""
        glViewport(0, 0, width, height)
        self.width = width
        self.height = height

        aspect = height / width
        near = .1
        # see https://stackoverflow.com/a/16459424/4457767
        self.set_projection_matrix(
            Mat4.frustrum(-near, near, -near*aspect, near*aspect, 2*near, 1e7)
        )
Ejemplo n.º 17
0
    def draw_rocket(self):
        """Draw the rocket"""

        self.add_pick_object(self.rocket)

        # rocket orientation
        row1, row2, row3 = self.rocket.orientation
        orientation = Mat4([
            [*row1, 0],
            [*row2, 0],
            [*row3, 0],
            [0, 0, 0, 1],
        ])

        original_modelview_matrix = self.modelview_matrix
        transform = self.modelview_matrix @ \
            Mat4.translate(*self.rocket._relative_position) @ \
            Mat4.scale(1e4, 1e4, 1e4) @ \
            orientation
        self.set_modelview_matrix(transform)

        # pick correct texture
        if self.rocket.throttle == 0:
            glBindTexture(GL_TEXTURE_2D, self.texture_rocket_off)
        else:
            glBindTexture(GL_TEXTURE_2D, self.texture_rocket_on)

        # draw texture
        glDisable(GL_CULL_FACE)
        self.set_color(1, 1, 1, 1)
        self.rocket_mesh.draw()
        glEnable(GL_CULL_FACE)

        # all done
        glBindTexture(GL_TEXTURE_2D, 0)
        self.set_modelview_matrix(original_modelview_matrix)
Ejemplo n.º 18
0
    def draw(self):
        """Draw the scene"""
        # ancestors_descendants() can just be assumed to return all celestial
        # bodies, except that ancestors are in a separate list
        ancestors, descendants = ancestors_descendants(self.focus)
        bodies = ancestors + descendants

        # cache position of celestial bodies relative to the scene origin
        scene_origin = self.focus.global_position_at_time(self.time)
        for body in bodies:
            body_position = body.global_position_at_time(self.time)
            body._relative_position = body_position - scene_origin

        # draw celestial bodies
        # draw system star individually (without lighting)
        self.draw_body(self.system)
        # enable lighting and place light source
        self.shader_set(self.shader_lighting)
        x, y, z, _ = self.modelview_matrix @ self.system._relative_position
        glUniform3f(self.lighting_source, x, y, z)
        # draw planets and moons (with lighting)
        self.sphere.bind()
        for body in bodies:
            if body is self.system:
                continue
            self.draw_body(body)
        self.sphere.unbind()
        # clean
        self.shader_set()

        # draw circles around celestial bodies when from far away
        glPointSize(20)
        glDepthMask(False)
        self.shader_set(self.shader_position_marker)
        self.set_color(1, 0, 0, 0.5)
        self.clear_pick_object()
        points = (body._relative_position for body in bodies)
        gspyce.mesh.Generic(GL_POINTS, points).draw()
        self.shader_set()
        glDepthMask(True)

        # draw orbits
        glPointSize(5)
        self.set_color(1.0, 1.0, 0.0, 0.2)
        original_modelview_matrix = self.modelview_matrix
        for body in descendants:  # skip ancestors (see below)
            self.set_modelview_matrix(
                original_modelview_matrix @
                Mat4.translate(*body.orbit.primary._relative_position)
            )
            self.add_pick_object(body)
            if not hasattr(body.orbit, "mesh"):
                body.orbit.mesh = gspyce.mesh.OrbitMesh(body.orbit)
                body.orbit.apses_mesh = gspyce.mesh.ApsesMesh(body.orbit)
            body.orbit.mesh.draw()
            body.orbit.apses_mesh.draw()
        self.set_modelview_matrix(original_modelview_matrix)

        # separately draw orbits of ancestors
        # since the focused celestial body  and its ancestors are relatively
        # close to the camera, it is best to draw them with the origin the
        # orbit, rather than at the primary
        self.set_color(1.0, 1.0, 0.0, 1.0)
        for body in ancestors:
            if body.orbit is None:
                continue
            original_modelview_matrix = self.modelview_matrix
            self.set_modelview_matrix(
                self.modelview_matrix @
                Mat4.translate(*body._relative_position)
            )
            self.add_pick_object(body)
            gspyce.mesh.FocusedOrbitMesh(body.orbit, self.time).draw()
            gspyce.mesh.FocusedApsesMesh(body.orbit, self.time).draw()
            self.set_modelview_matrix(original_modelview_matrix)
Ejemplo n.º 19
0
    def draw(self):
        """Draw the scene"""
        # ancestors_descendants() can just be assumed to return all celestial
        # bodies, except that ancestors are in a separate list
        ancestors, descendants = ancestors_descendants(self.focus)
        bodies = ancestors + descendants

        # cache position of celestial bodies relative to the scene origin
        scene_origin = self.focus.global_position_at_time(self.time)
        for body in bodies:
            body_position = body.global_position_at_time(self.time)
            body._relative_position = body_position - scene_origin

        # draw celestial bodies
        # draw system star individually (without lighting)
        self.draw_body(self.system)
        # enable lighting and place light source
        self.shader_set(self.shader_lighting)
        x, y, z, _ = self.modelview_matrix @ self.system._relative_position
        glUniform3f(self.lighting_source, x, y, z)
        # draw planets and moons (with lighting)
        self.sphere.bind()
        for body in bodies:
            if body is self.system:
                continue
            self.draw_body(body)
        self.sphere.unbind()
        # clean
        self.shader_set()

        # draw circles around celestial bodies when from far away
        glPointSize(20)
        glDepthMask(False)
        self.shader_set(self.shader_position_marker)
        self.set_color(1, 0, 0, 0.5)
        self.clear_pick_object()
        points = (body._relative_position for body in bodies)
        gspyce.mesh.Generic(GL_POINTS, points).draw()
        self.shader_set()
        glDepthMask(True)

        # draw orbits
        glPointSize(5)
        self.set_color(1.0, 1.0, 0.0, 0.2)
        original_modelview_matrix = self.modelview_matrix
        for body in descendants:  # skip ancestors (see below)
            self.set_modelview_matrix(
                original_modelview_matrix
                @ Mat4.translate(*body.orbit.primary._relative_position))
            self.add_pick_object(body)
            if not hasattr(body.orbit, "mesh"):
                body.orbit.mesh = gspyce.mesh.OrbitMesh(body.orbit)
                body.orbit.apses_mesh = gspyce.mesh.ApsesMesh(body.orbit)
            body.orbit.mesh.draw()
            body.orbit.apses_mesh.draw()
        self.set_modelview_matrix(original_modelview_matrix)

        # separately draw orbits of ancestors
        # since the focused celestial body  and its ancestors are relatively
        # close to the camera, it is best to draw them with the origin the
        # orbit, rather than at the primary
        self.set_color(1.0, 1.0, 0.0, 1.0)
        for body in ancestors:
            if body.orbit is None:
                continue
            original_modelview_matrix = self.modelview_matrix
            self.set_modelview_matrix(
                self.modelview_matrix
                @ Mat4.translate(*body._relative_position))
            self.add_pick_object(body)
            gspyce.mesh.FocusedOrbitMesh(body.orbit, self.time).draw()
            gspyce.mesh.FocusedApsesMesh(body.orbit, self.time).draw()
            self.set_modelview_matrix(original_modelview_matrix)