Example #1
0
    def _make_cursor_view_matrix(self, x, y):

        "Calculate a view matrix for placing the custom cursor on screen."

        ww, wh = self.get_size()
        iw, ih = self.mouse_texture.size

        scale = 1
        width = ww / iw / scale
        height = wh / ih / scale
        far = 10
        near = -10

        frust = Matrix4()
        frust[:] = (2 / width, 0, 0, 0, 0, 2 / height, 0, 0, 0, 0,
                    -2 / (far - near), 0, 0, 0, -(far + near) / (far - near),
                    1)

        x -= ww / 2
        y -= wh / 2
        lx = x / iw / scale
        ly = y / ih / scale

        view = Matrix4().new_translate(lx, ly, 0)

        return frust * view
Example #2
0
 def generate_transform_matrix(self):
     m_rotate_base = Matrix4.new_look_at(
         Point3(0, 0, 0),
         -self.origin.direction,
         self.origin.up).inverse()
     m = Matrix4.new_look_at(
         Point3(0, 0, 0),
         -self.position.direction,
         self.position.up) * m_rotate_base
     move = self.position.position - self.origin.position
     m.d, m.h, m.l = move.x, move.y, move.z
     return m
def on_draw():
    a = 1.6
    b = a * sqrt(3) / 3
    r = sqrt(1 - b * b)
    R = Vector3(a, a, a).normalized() * b
    cs = Matrix4.new_translate(R[0], R[1], R[2]) * Matrix4.new_look_at(
        Vector3(0, 0, 0), R, Vector3(0, 1, 0))

    glDisable(GL_DEPTH_TEST)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
    glLoadIdentity()
    draw_coords(Matrix4.new_identity(), 2)
    draw_line((0, 0, 0), R, (1, 1, 0))
    draw_coords(cs, r, 3)
    glEnable(GL_DEPTH_TEST)
    draw_triangle((a, 0, 0), (0, a, 0), (0, 0, a), (.5, .5, 1), .2)
    draw_sphere(3, (1, .5, .5), .2)
Example #4
0
def make_view_matrix(window_size, image_size, zoom, offset):
    "Calculate a view matrix that places the image on the screen, at scale."
    ww, wh = window_size
    iw, ih = image_size

    scale = 2**zoom
    width = ww / iw / scale
    height = wh / ih / scale
    far = 10
    near = -10

    frust = Matrix4()
    frust[:] = (2 / width, 0, 0, 0, 0, 2 / height, 0, 0, 0, 0,
                -2 / (far - near), 0, 0, 0, -(far + near) / (far - near), 1)

    x, y = offset
    lx = x / iw / scale
    ly = y / ih / scale

    view = (Matrix4().new_translate(lx, ly, 0))

    return frust * view
Example #5
0
    def _orig_euclid_look_at(eye, at, up):
        '''
        Taken from the original source of PyEuclid's Matrix4.new_look_at() 
        prior to 1184a07d119a62fc40b2c6becdbeaf053a699047 (11 Jan 2015), 
        as discussed here:
        https://github.com/ezag/pyeuclid/commit/1184a07d119a62fc40b2c6becdbeaf053a699047
    
        We were dependent on the old behavior, which is duplicated here:
        '''
        z = (eye - at).normalized()
        x = up.cross(z).normalized()
        y = z.cross(x)

        m = Matrix4.new_rotate_triple_axis(x, y, z)
        m.d, m.h, m.l = eye.x, eye.y, eye.z
        return m
Example #6
0
    def on_draw(self):

        # Prevent trying to draw before things have been set up
        if not hasattr(self, "offscreen_buffer"):
            return

        # Model matrix we'll use to position the main model
        suzanne_model_matrix = (Matrix4.new_identity().rotatex(
            -math.pi / 2).rotatez(time()))  # Rotate over time
        plane_model_matrix = Matrix4.new_rotatey(math.pi).translate(0, 0, 2)

        # Render to an offscreen buffer
        with self.offscreen_buffer, self.view_program, \
                enabled(gl.GL_DEPTH_TEST), disabled(gl.GL_CULL_FACE):

            gl.glDepthMask(gl.GL_TRUE)

            w, h = self.size
            aspect = h / w

            # Calculate a view frustum; this is basically our camera.
            near = 5
            far = 15
            width = 2
            height = 2 * aspect
            frustum = (Matrix4.new(near / width, 0, 0, 0, 0, near / height, 0,
                                   0, 0, 0, -(far + near) / (far - near), -1,
                                   0, 0, -2 * far * near / (far - near), 0))

            # The view matrix positions the camera in the scene
            view_matrix = (Matrix4.new_identity().translate(0, 0, -8))

            # Send the matrices to GL
            gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE,
                                  gl_matrix(frustum * view_matrix))
            gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE,
                                  gl_matrix(suzanne_model_matrix))

            gl.glUniform4f(2, 0.3, 0.3, 1,
                           1)  # Set the "color" uniform to blue
            self.suzanne.draw()

            # We'll also draw a simple plane behind the main model
            gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE,
                                  gl_matrix(plane_model_matrix))
            gl.glUniform4f(2, 0.3, 1, 0.3,
                           1)  # Set the "color" uniform to green
            self.plane.draw(mode=gl.GL_TRIANGLE_STRIP)

        # Render shadow buffer
        # Basically the same scene as above, but to a different buffer and from a different view
        with self.shadow_buffer, self.view_program, enabled(
                gl.GL_DEPTH_TEST), disabled(gl.GL_CULL_FACE):
            gl.glDepthMask(gl.GL_TRUE)

            frustum = Matrix4.new_perspective(1, 1, 1, 12)
            view_matrix = (Matrix4.new_identity().translate(
                0, 0, -4).rotatey(0.5).rotatex(0.3))
            light_pos = (view_matrix.inverse() * Point3(0, 0, 0))
            light_view_matrix = frustum * view_matrix
            gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE,
                                  gl_matrix(light_view_matrix))
            gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE,
                                  gl_matrix(suzanne_model_matrix))
            gl.glUniform4f(2, 0.9, 0.3, 0.4, 1)
            self.suzanne.draw()

            gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE,
                                  gl_matrix(plane_model_matrix))
            self.plane.draw(mode=gl.GL_TRIANGLE_STRIP)

        # Now draw the offscreen buffer to another buffer, combining it with the
        # lighting information to get a nice image.
        # Note: This step is pretty pointless here, as we might just draw directly to screen.
        # Just demonstrates how to do it.
        with self.vao, self.offscreen_buffer2, self.lighting_program, disabled(
                gl.GL_CULL_FACE, gl.GL_DEPTH_TEST):
            gl.glUniform3f(0, *light_pos)
            gl.glUniformMatrix4fv(1, 1, gl.GL_FALSE,
                                  gl_matrix(light_view_matrix))
            # Bind some of the offscreen buffer's textures so the shader can read them.
            with self.offscreen_buffer["color"], self.offscreen_buffer["normal"], \
                    self.offscreen_buffer["position"], self.shadow_buffer["depth"]:
                gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)

        # Now render the finished image to the screen
        with self.vao, self.copy_program, disabled(gl.GL_CULL_FACE,
                                                   gl.GL_DEPTH_TEST):
            with self.offscreen_buffer2["color"]:
                gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)
Example #7
0
    def __call__(self, oldpaint, imgui, drawing, brush,
                 altitude: float=-120, azimuth: float=0, spin: bool=False):
        selection = drawing.selection
        if selection:
            size = selection.size
            depth = len(drawing.layers)
            colors = drawing.palette.as_tuple()

            mesh = self._get_mesh(tuple(drawing.layers), selection, colors)
            if not mesh:
                # TODO hacky
                self.texture and self.texture[0].clear()
                return

            w, h = size
            model_matrix = Matrix4.new_translate(-w/2, -h/2, depth/2).scale(1, 1, 1/math.sin(math.pi/3))

            far = w*2
            near = 0
            frust = Matrix4()
            frust[:] = (2/w, 0, 0, 0,
                        0, 2/h, 0, 0,
                        0, 0, -2/(far-near), 0,
                        0, 0, -(far+near)/(far-near), 1)
            
            offscreen_buffer = self._get_buffer(size)
            with offscreen_buffer, self.program, \
                    enabled(gl.GL_DEPTH_TEST), disabled(gl.GL_CULL_FACE):

                azimuth = math.degrees(time()) if spin else azimuth
                view_matrix = (
                    Matrix4
                    # .new_scale(2/w, 2/h, 1/max(w, h))
                    .new_translate(0, 0, -w)
                    .rotatex(math.radians(altitude))
                    .rotatez(math.radians(azimuth))  # Rotate over time
                )
                
                gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE,
                                      gl_matrix(frust * view_matrix * model_matrix))

                gl.glViewport(0, 0, *size)
                gl.glPointSize(1.0)

                mesh.draw(mode=gl.GL_POINTS)

            shadow_buffer = self._get_shadow_buffer(size)                
            with shadow_buffer, self.program, \
                    enabled(gl.GL_DEPTH_TEST), disabled(gl.GL_CULL_FACE):
                view_matrix = (
                    Matrix4
                    # .new_scale(2/w, 2/h, 1/max(w, h))
                    .new_translate(0, 0, -5)
                    .rotatex(math.pi)
                    .rotatez(azimuth)  # Rotate over time
                )
                gl.glUniformMatrix4fv(0, 1, gl.GL_FALSE,
                                      gl_matrix(frust * view_matrix * model_matrix))

                gl.glViewport(0, 0, *size)
                gl.glPointSize(1.0)

                mesh.draw(mode=gl.GL_POINTS)

            final_buffer = self._get_final_buffer(size)
            
            with self._vao, final_buffer, self._copy_program, disabled(gl.GL_CULL_FACE, gl.GL_DEPTH_TEST):
                with offscreen_buffer["color"], offscreen_buffer["normal"], offscreen_buffer["position"], shadow_buffer["depth"]:
                    gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)
                
            # TODO must be careful here so that the texture is always valid
            # (since imgui may read it at any time) Find a way to ensure this.
            texture = self._get_texture(size)
            gl.glCopyImageSubData(final_buffer["color"].name, gl.GL_TEXTURE_2D, 0, 0, 0, 0,
                                  texture.name, gl.GL_TEXTURE_2D, 0, 0, 0, 0,
                                  w, h, 1)
            self.texture = texture, size
Example #8
0
    def __call__(self,
                 voxpaint,
                 drawing,
                 altitude: float = 120,
                 azimuth: float = 45,
                 spin: bool = False):

        size = drawing.size
        depth = drawing.shape[2]
        colors = drawing.palette.colors

        x = math.sin(math.pi / 3)

        altitude = math.radians(altitude)
        azimuth = math.radians(azimuth)

        mesh = self._get_mesh(drawing, drawing.version,
                              drawing.hidden_layers_by_axis)
        if not mesh:
            # TODO hacky
            self.texture and self.texture[0].clear()
            return

        w, h = size
        vw = int(w * math.sqrt(2))
        vh = int(h + math.sqrt(2) * h // 2)
        view_size = (vw, vh)
        model_matrix = (Matrix4.new_scale(1, 1, 1 / x).translate(
            -w // 2, -h // 2, depth // 2 - 1 / 2))

        far = w * 2
        near = -w * 2
        frust = Matrix4()
        frust[:] = (2 / vw, 0, 0, 0, 0, 2 / vh, 0, 0, 0, 0, -2 / (far - near),
                    0, 0, 0, -(far + near) / (far - near), 1)

        offscreen_buffer = self._get_buffer(view_size)
        with offscreen_buffer, self.program, \
                enabled(gl.GL_DEPTH_TEST), disabled(gl.GL_CULL_FACE):

            azimuth = time() if spin else azimuth
            view_matrix = (
                Matrix4.new_translate(0, 0, -1).rotatex(altitude).rotatez(
                    azimuth)  # Rotate over time
            )
            colors = self._get_colors(colors)
            gl.glUniform4fv(3, 256, colors)

            gl.glUniformMatrix4fv(
                0, 1, gl.GL_FALSE,
                gl_matrix(frust * view_matrix * model_matrix))
            gl.glViewport(0, 0, vw, vh)
            gl.glPointSize(1)

            mesh.draw(mode=gl.GL_POINTS)

        final_buffer = self._get_final_buffer(view_size)

        with self._vao, final_buffer, self._copy_program, disabled(
                gl.GL_CULL_FACE, gl.GL_DEPTH_TEST):
            with offscreen_buffer["color"], offscreen_buffer[
                    "normal"], offscreen_buffer["position"]:
                gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6)

        # TODO must be careful here so that the texture is always valid
        # (since imgui may read it at any time) Find a way to ensure this.
        texture = self._get_texture(view_size)
        gl.glCopyImageSubData(final_buffer["color"].name, gl.GL_TEXTURE_2D, 0,
                              0, 0, 0, texture.name, gl.GL_TEXTURE_2D, 0, 0, 0,
                              0, vw, vh, 1)
        self.texture = texture, view_size