class TriangleUnderlayRenderer(QObject):
    def __init__(self, parent=None):
        super(TriangleUnderlayRenderer, self).__init__(parent)
        self._shader_program = None
        self._viewport_size = QSize()
        self._window = None

    @pyqtSlot()
    def paint(self):

        # TODO test on Ubuntu
        # for Darwin, it's a must
        gl = self._window.openglContext().versionFunctions()

        if self._shader_program is None:
            self._shader_program = QOpenGLShaderProgram()
            self._shader_program.addShaderFromSourceFile(
                QOpenGLShader.Vertex, 'shaders/OpenGL_2_1/vertex.glsl')
            self._shader_program.addShaderFromSourceFile(
                QOpenGLShader.Fragment, 'shaders/OpenGL_2_1/fragment.glsl')
            self._shader_program.bindAttributeLocation('position', 0)
            self._shader_program.bindAttributeLocation('color', 1)
            self._shader_program.link()

        self._shader_program.bind()
        self._shader_program.enableAttributeArray(0)
        self._shader_program.enableAttributeArray(1)

        self._shader_program.setAttributeArray(0, positions)
        self._shader_program.setAttributeArray(1, colors)

        gl.glViewport(0, 0, self._viewport_size.width(),
                      self._viewport_size.height())

        gl.glClearColor(0.5, 0.5, 0.5, 1)
        gl.glDisable(gl.GL_DEPTH_TEST)

        gl.glClear(gl.GL_COLOR_BUFFER_BIT)

        gl.glDrawArrays(gl.GL_TRIANGLES, 0, 3)

        self._shader_program.disableAttributeArray(0)
        self._shader_program.disableAttributeArray(1)

        self._shader_program.release()

        # Restore the OpenGL state for QtQuick rendering
        self._window.resetOpenGLState()
        self._window.update()

    def set_viewport_size(self, size):
        self._viewport_size = size

    def set_window(self, window):
        self._window = window
Exemple #2
0
class GLWidget(QGLWidget):

    clicked = pyqtSignal()

    PROGRAM_VERTEX_ATTRIBUTE, PROGRAM_TEXCOORD_ATTRIBUTE = range(2)

    vsrc = """
attribute highp vec4 vertex;
attribute mediump vec4 texCoord;
varying mediump vec4 texc;
uniform mediump mat4 matrix;
void main(void)
{
    gl_Position = matrix * vertex;
    texc = texCoord;
}
"""

    fsrc = """
uniform sampler2D texture;
varying mediump vec4 texc;
void main(void)
{
    gl_FragColor = texture2D(texture, texc.st);
}
"""

    coords = (((+1, -1, -1), (-1, -1, -1), (-1, +1, -1), (+1, +1, -1)),
              ((+1, +1, -1), (-1, +1, -1), (-1, +1, +1), (+1, +1, +1)),
              ((+1, -1, +1), (+1, -1, -1), (+1, +1, -1), (+1, +1, +1)),
              ((-1, -1, -1), (-1, -1, +1), (-1, +1, +1),
               (-1, +1, -1)), ((+1, -1, +1), (-1, -1, +1), (-1, -1, -1),
                               (+1, -1, -1)), ((-1, -1, +1), (+1, -1, +1),
                                               (+1, +1, +1), (-1, +1, +1)))

    def __init__(self, parent=None, shareWidget=None):
        super(GLWidget, self).__init__(parent, shareWidget)

        self.clearColor = Qt.black
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0

        self.clearColor = QColor()
        self.lastPos = QPoint()

        self.program = None

    def minimumSizeHint(self):
        return QSize(50, 50)

    def sizeHint(self):
        return QSize(200, 200)

    def rotateBy(self, xAngle, yAngle, zAngle):
        self.xRot += xAngle
        self.yRot += yAngle
        self.zRot += zAngle
        self.updateGL()

    def setClearColor(self, color):
        self.clearColor = color
        self.updateGL()

    def initializeGL(self):
        self.makeObject()

        glEnable(GL_DEPTH_TEST)
        glEnable(GL_CULL_FACE)

        vshader = QOpenGLShader(QOpenGLShader.Vertex, self)
        vshader.compileSourceCode(self.vsrc)

        fshader = QOpenGLShader(QOpenGLShader.Fragment, self)
        fshader.compileSourceCode(self.fsrc)

        self.program = QOpenGLShaderProgram(self)
        self.program.addShader(vshader)
        self.program.addShader(fshader)
        self.program.bindAttributeLocation('vertex',
                                           self.PROGRAM_VERTEX_ATTRIBUTE)
        self.program.bindAttributeLocation('texCoord',
                                           self.PROGRAM_TEXCOORD_ATTRIBUTE)
        self.program.link()

        self.program.bind()
        self.program.setUniformValue('texture', 0)

        self.program.enableAttributeArray(self.PROGRAM_VERTEX_ATTRIBUTE)
        self.program.enableAttributeArray(self.PROGRAM_TEXCOORD_ATTRIBUTE)
        self.program.setAttributeArray(self.PROGRAM_VERTEX_ATTRIBUTE,
                                       self.vertices)
        self.program.setAttributeArray(self.PROGRAM_TEXCOORD_ATTRIBUTE,
                                       self.texCoords)

    def paintGL(self):
        self.qglClearColor(self.clearColor)
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        m = QMatrix4x4()
        m.ortho(-0.5, 0.5, 0.5, -0.5, 4.0, 15.0)
        m.translate(0.0, 0.0, -10.0)
        m.rotate(self.xRot / 16.0, 1.0, 0.0, 0.0)
        m.rotate(self.yRot / 16.0, 0.0, 1.0, 0.0)
        m.rotate(self.zRot / 16.0, 0.0, 0.0, 1.0)

        self.program.setUniformValue('matrix', m)

        for i in range(6):
            glBindTexture(GL_TEXTURE_2D, self.textures[i])
            glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4)

    def resizeGL(self, width, height):
        side = min(width, height)
        glViewport((width - side) // 2, (height - side) // 2, side, side)

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.rotateBy(8 * dy, 8 * dx, 0)
        elif event.buttons() & Qt.RightButton:
            self.rotateBy(8 * dy, 0, 8 * dx)

        self.lastPos = event.pos()

    def mouseReleaseEvent(self, event):
        self.clicked.emit()

    def makeObject(self):
        self.textures = []
        self.texCoords = []
        self.vertices = []

        for i in range(6):
            self.textures.append(
                self.bindTexture(QPixmap(':/images/side%d.png' % (i + 1))))

            for j in range(4):
                self.texCoords.append(((j == 0 or j == 3), (j == 0 or j == 1)))

                x, y, z = self.coords[i][j]
                self.vertices.append((0.2 * x, 0.2 * y, 0.2 * z))
Exemple #3
0
class LogoRenderer():  #protected QOpenGLFunctions
    """docstring for LogoRenderer"""
    def __init__(self):
        super(LogoRenderer, self).__init__()
        self.m_fAngle = None
        self.m_fScale = None
        self.vertices = []
        self.normals = []
        self.program1 = QOpenGLShaderProgram()
        self.vertexAttr1 = 0
        self.normalAttr1 = 0
        self.matrixUniform1 = 0

        ver = QOpenGLVersionProfile()
        ver.setVersion(2, 1)
        cntx = QOpenGLContext.currentContext()
        #print("QOpenGLContext:", cntx, ver)
        fmt = cntx.format()
        fmt.setVersion(2, 1)
        cntx.setFormat(fmt)
        self.gl = cntx.versionFunctions(ver)

    def render(self):
        self.gl.glDepthMask(True)

        self.gl.glClearColor(0.5, 0.5, 0.7, 1.0)
        self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT
                        | self.gl.GL_DEPTH_BUFFER_BIT)

        self.gl.glTexParameteri(self.gl.GL_TEXTURE_2D,
                                self.gl.GL_TEXTURE_MIN_FILTER,
                                self.gl.GL_LINEAR)
        self.gl.glTexParameteri(self.gl.GL_TEXTURE_2D,
                                self.gl.GL_TEXTURE_MAG_FILTER,
                                self.gl.GL_LINEAR)

        self.gl.glFrontFace(self.gl.GL_CW)
        self.gl.glCullFace(self.gl.GL_FRONT)
        self.gl.glEnable(self.gl.GL_CULL_FACE)
        self.gl.glEnable(self.gl.GL_DEPTH_TEST)

        modelview = QMatrix4x4()
        modelview.rotate(self.m_fAngle, 0.0, 1.0, 0.0)
        modelview.rotate(self.m_fAngle, 1.0, 0.0, 0.0)
        modelview.rotate(self.m_fAngle, 0.0, 0.0, 1.0)
        modelview.scale(self.m_fScale)
        modelview.translate(0.0, -0.2, 0.0)

        self.program1.bind()
        self.program1.setUniformValue(self.matrixUniform1, modelview)
        self.paintQtLogo()
        self.program1.release()

        self.gl.glDisable(self.gl.GL_DEPTH_TEST)
        self.gl.glDisable(self.gl.GL_CULL_FACE)

        self.m_fAngle += 1.0

    def initialize(self):
        #print("initialize.gls")
        self.gl.initializeOpenGLFunctions()

        self.gl.glClearColor(0.1, 0.1, 0.2, 1.0)

        vshader1 = QOpenGLShader(QOpenGLShader.Vertex, self.program1)
        vsrc1 = str("attribute highp vec4 vertex;\n"
                    "attribute mediump vec3 normal;\n"
                    "uniform mediump mat4 matrix;\n"
                    "varying mediump vec4 color;\n"
                    "void main(void)\n"
                    "{\n"
                    "    vec3 toLight = normalize(vec3(0.0, 0.3, 1.0));\n"
                    "    float angle = max(dot(normal, toLight), 0.0);\n"
                    "    vec3 col = vec3(0.40, 1.0, 0.0);\n"
                    "    color = vec4(col * 0.2 + col * 0.8 * angle, 1.0);\n"
                    "    color = clamp(color, 0.0, 1.0);\n"
                    "    gl_Position = matrix * vertex;\n"
                    "}\n")
        vshader1.compileSourceCode(vsrc1)

        fshader1 = QOpenGLShader(QOpenGLShader.Fragment, self.program1)
        fsrc1 = str("varying mediump vec4 color;\n"
                    "void main(void)\n"
                    "{\n"
                    "    gl_FragColor = color;\n"
                    "}\n")
        fshader1.compileSourceCode(fsrc1)

        self.program1.addShader(vshader1)
        self.program1.addShader(fshader1)
        self.program1.link()

        self.vertexAttr1 = self.program1.attributeLocation("vertex")
        self.normalAttr1 = self.program1.attributeLocation("normal")
        self.matrixUniform1 = self.program1.uniformLocation("matrix")

        self.gl.glTexParameteri(self.gl.GL_TEXTURE_2D,
                                self.gl.GL_TEXTURE_MIN_FILTER,
                                self.gl.GL_LINEAR)
        self.gl.glTexParameteri(self.gl.GL_TEXTURE_2D,
                                self.gl.GL_TEXTURE_MAG_FILTER,
                                self.gl.GL_LINEAR)

        self.m_fAngle = 0
        self.m_fScale = 1
        self.createGeometry()

    def paintQtLogo(self):
        self.program1.enableAttributeArray(self.normalAttr1)
        self.program1.enableAttributeArray(self.vertexAttr1)
        self.program1.setAttributeArray(self.vertexAttr1, self.vertices)
        self.program1.setAttributeArray(self.normalAttr1, self.normals)
        self.gl.glDrawArrays(self.gl.GL_TRIANGLES, 0, len(self.vertices))
        self.program1.disableAttributeArray(self.normalAttr1)
        self.program1.disableAttributeArray(self.vertexAttr1)

    def createGeometry(self):
        self.vertices.clear()
        self.normals.clear()

        x1 = +0.06
        y1 = -0.14
        x2 = +0.14
        y2 = -0.06
        x3 = +0.08
        y3 = +0.00
        x4 = +0.30
        y4 = +0.22

        self.quad(x1, y1, x2, y2, y2, x2, y1, x1)
        self.quad(x3, y3, x4, y4, y4, x4, y3, x3)

        self.extrude(x1, y1, x2, y2)
        self.extrude(x2, y2, y2, x2)
        self.extrude(y2, x2, y1, x1)
        self.extrude(y1, x1, x1, y1)
        self.extrude(x3, y3, x4, y4)
        self.extrude(x4, y4, y4, x4)
        self.extrude(y4, x4, y3, x3)

        NumSectors = 100

        for i in range(NumSectors):
            angle1 = (i * 2 * math.pi) / NumSectors
            x5 = 0.30 * math.sin(angle1)
            y5 = 0.30 * math.cos(angle1)
            x6 = 0.20 * math.sin(angle1)
            y6 = 0.20 * math.cos(angle1)

            angle2 = ((i + 1) * 2 * math.pi) / NumSectors
            x7 = 0.20 * math.sin(angle2)
            y7 = 0.20 * math.cos(angle2)
            x8 = 0.30 * math.sin(angle2)
            y8 = 0.30 * math.cos(angle2)

            self.quad(x5, y5, x6, y6, x7, y7, x8, y8)

            self.extrude(x6, y6, x7, y7)
            self.extrude(x8, y8, x5, y5)

        for i in range(len(self.vertices)):
            self.vertices[i] *= 2.0

    def quad(self, x1, y1, x2, y2, x3, y3, x4, y4):
        #print("quad inicio")
        self.vertices.append(QVector3D(x1, y1, -0.05))
        self.vertices.append(QVector3D(x2, y2, -0.05))
        self.vertices.append(QVector3D(x4, y4, -0.05))

        self.vertices.append(QVector3D(x3, y3, -0.05))
        self.vertices.append(QVector3D(x4, y4, -0.05))
        self.vertices.append(QVector3D(x2, y2, -0.05))

        n = QVector3D.normal(QVector3D(x2 - x1, y2 - y1, 0.0),
                             QVector3D(x4 - x1, y4 - y1, 0.0))

        for i in range(6):
            self.normals.append(n)

        self.vertices.append(QVector3D(x4, y4, 0.05))
        self.vertices.append(QVector3D(x2, y2, 0.05))
        self.vertices.append(QVector3D(x1, y1, 0.05))

        self.vertices.append(QVector3D(x2, y2, 0.05))
        self.vertices.append(QVector3D(x4, y4, 0.05))
        self.vertices.append(QVector3D(x3, y3, 0.05))

        n = QVector3D.normal(QVector3D(x2 - x4, y2 - y4, 0.0),
                             QVector3D(x1 - x4, y1 - y4, 0.0))

        for i in range(6):
            self.normals.append(n)
        #print("quad fin")

    def extrude(self, x1, y1, x2, y2):
        #print("extrude inicio")
        self.vertices.append(QVector3D(x1, y1, +0.05))
        self.vertices.append(QVector3D(x2, y2, +0.05))
        self.vertices.append(QVector3D(x1, y1, -0.05))

        self.vertices.append(QVector3D(x2, y2, -0.05))
        self.vertices.append(QVector3D(x1, y1, -0.05))
        self.vertices.append(QVector3D(x2, y2, +0.05))

        n = QVector3D.normal(QVector3D(x2 - x1, y2 - y1, 0.0),
                             QVector3D(0.0, 0.0, -0.1))

        for i in range(6):
            self.normals.append(n)
class MyWidget(QtOpenGL.QGLWidget):
    def __init__(self, parent=None):
        super(MyWidget, self).__init__(parent)

        self.quadCoord = np.array([[-1., -1., 0.], [1., -1., 0.], [1., 1., 0.],
                                   [1., 1., 0.], [-1., 1., 0.], [-1., -1.,
                                                                 0.]])

        self.quadCoordTex = np.array([[0, 0], [1., 0.], [1., 1.], [1., 1.],
                                      [0, 1.], [0, 0]])

    def initializeGL(self):
        GL.glClearColor(1.0, 0.0, 0.0, 1.0)
        GL.glEnable(GL.GL_BLEND)
        GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
        GL.glClear(GL.GL_COLOR_BUFFER_BIT)

        print("OpenGL.GL: " + str(GL.glGetString(GL.GL_VERSION)))
        print("GL.GLSL: " +
              str(GL.glGetString(GL.GL_SHADING_LANGUAGE_VERSION)))
        print("OpenGL ATTRIBUTES:\n",
              ", ".join(d for d in dir(GL) if d.startswith("GL_")))

        self.program = QOpenGLShaderProgram()
        self.program.addShaderFromSourceCode(
            QOpenGLShader.Vertex, """#version 120
        attribute vec2 position;
        attribute vec2 texcoord;
        varying vec2 mytexcoord;
        void main() {
            gl_Position = vec4(position, 0., 1.0);
            mytexcoord = texcoord;
        }""")

        self.program.addShaderFromSourceCode(
            QOpenGLShader.Fragment, """#version 120
        uniform sampler2D texture;
        varying vec2 mytexcoord;
        void main() {
            
            gl_FragColor = texture2D(texture,mytexcoord);
        }""")
        print(self.program.log())
        self.program.link()

        self.texture = fillTexture2d(
            np.outer(np.linspace(0, 1, 128), np.ones(128)))

    def paintGL(self):
        #GL.glClear(GL.GL_COLOR_BUFFER_BIT)
        self.program.bind()

        self.program.enableAttributeArray("position")
        self.program.enableAttributeArray("texcoord")
        self.program.setAttributeArray("position", self.quadCoord)
        self.program.setAttributeArray("texcoord", self.quadCoordTex)

        GL.glActiveTexture(GL.GL_TEXTURE0)
        GL.glBindTexture(GL.GL_TEXTURE_2D, self.texture)
        self.program.setUniformValue("texture", 0)

        GL.glDrawArrays(GL.GL_TRIANGLES, 0, len(self.quadCoord))
Exemple #5
0
class GLWidget(QOpenGLWidget):

    clicked = pyqtSignal()

    PROGRAM_VERTEX_ATTRIBUTE, PROGRAM_TEXCOORD_ATTRIBUTE = range(2)

    vsrc = """
attribute highp vec4 vertex;
attribute mediump vec4 texCoord;
varying mediump vec4 texc;
uniform mediump mat4 matrix;
void main(void)
{
    gl_Position = matrix * vertex;
    texc = texCoord;
}
"""

    fsrc = """
uniform sampler2D texture;
varying mediump vec4 texc;
void main(void)
{
    gl_FragColor = texture2D(texture, texc.st);
}
"""

    coords = (
        ((+1, -1, -1), (-1, -1, -1), (-1, +1, -1), (+1, +1, -1)),
        ((+1, +1, -1), (-1, +1, -1), (-1, +1, +1), (+1, +1, +1)),
        ((+1, -1, +1), (+1, -1, -1), (+1, +1, -1), (+1, +1, +1)),
        ((-1, -1, -1), (-1, -1, +1), (-1, +1, +1), (-1, +1, -1)),
        ((+1, -1, +1), (-1, -1, +1), (-1, -1, -1), (+1, -1, -1)),
        ((-1, -1, +1), (+1, -1, +1), (+1, +1, +1), (-1, +1, +1)),
    )

    def __init__(self, parent=None):
        super(GLWidget, self).__init__(parent)

        self.clearColor = QColor(Qt.black)
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.program = None

        self.lastPos = QPoint()

    def minimumSizeHint(self):
        return QSize(50, 50)

    def sizeHint(self):
        return QSize(200, 200)

    def rotateBy(self, xAngle, yAngle, zAngle):
        self.xRot += xAngle
        self.yRot += yAngle
        self.zRot += zAngle
        self.update()

    def setClearColor(self, color):
        self.clearColor = color
        self.update()

    def initializeGL(self):
        version_profile = QOpenGLVersionProfile()
        version_profile.setVersion(2, 0)
        self.gl = self.context().versionFunctions(version_profile)
        self.gl.initializeOpenGLFunctions()

        self.makeObject()

        self.gl.glEnable(self.gl.GL_DEPTH_TEST)
        self.gl.glEnable(self.gl.GL_CULL_FACE)

        vshader = QOpenGLShader(QOpenGLShader.Vertex, self)
        vshader.compileSourceCode(self.vsrc)

        fshader = QOpenGLShader(QOpenGLShader.Fragment, self)
        fshader.compileSourceCode(self.fsrc)

        self.program = QOpenGLShaderProgram()
        self.program.addShader(vshader)
        self.program.addShader(fshader)
        self.program.bindAttributeLocation("vertex",
                                           self.PROGRAM_VERTEX_ATTRIBUTE)
        self.program.bindAttributeLocation("texCoord",
                                           self.PROGRAM_TEXCOORD_ATTRIBUTE)
        self.program.link()

        self.program.bind()
        self.program.setUniformValue("texture", 0)

        self.program.enableAttributeArray(self.PROGRAM_VERTEX_ATTRIBUTE)
        self.program.enableAttributeArray(self.PROGRAM_TEXCOORD_ATTRIBUTE)
        self.program.setAttributeArray(self.PROGRAM_VERTEX_ATTRIBUTE,
                                       self.vertices)
        self.program.setAttributeArray(self.PROGRAM_TEXCOORD_ATTRIBUTE,
                                       self.texCoords)

    def paintGL(self):
        self.gl.glClearColor(
            self.clearColor.redF(),
            self.clearColor.greenF(),
            self.clearColor.blueF(),
            self.clearColor.alphaF(),
        )
        self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT
                        | self.gl.GL_DEPTH_BUFFER_BIT)

        m = QMatrix4x4()
        m.ortho(-0.5, 0.5, 0.5, -0.5, 4.0, 15.0)
        m.translate(0.0, 0.0, -10.0)
        m.rotate(self.xRot / 16.0, 1.0, 0.0, 0.0)
        m.rotate(self.yRot / 16.0, 0.0, 1.0, 0.0)
        m.rotate(self.zRot / 16.0, 0.0, 0.0, 1.0)

        self.program.setUniformValue("matrix", m)

        for i, texture in enumerate(self.textures):
            texture.bind()
            self.gl.glDrawArrays(self.gl.GL_TRIANGLE_FAN, i * 4, 4)

    def resizeGL(self, width, height):
        side = min(width, height)
        self.gl.glViewport((width - side) // 2, (height - side) // 2, side,
                           side)

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.rotateBy(8 * dy, 8 * dx, 0)
        elif event.buttons() & Qt.RightButton:
            self.rotateBy(8 * dy, 0, 8 * dx)

        self.lastPos = event.pos()

    def mouseReleaseEvent(self, event):
        self.clicked.emit()

    def makeObject(self):
        self.textures = []
        self.texCoords = []
        self.vertices = []

        root = QFileInfo(__file__).absolutePath()

        for i in range(6):
            self.textures.append(
                QOpenGLTexture(
                    QImage(root + ("/images/side%d.png" %
                                   (i + 1))).mirrored()))

            for j in range(4):
                self.texCoords.append(((j == 0 or j == 3), (j == 0 or j == 1)))

                x, y, z = self.coords[i][j]
                self.vertices.append((0.2 * x, 0.2 * y, 0.2 * z))
class GLSliceWidget(QtOpenGL.QGLWidget):
    _dataModelChanged = QtCore.pyqtSignal()

    def __init__(self, parent=None, interpolation="linear", **kwargs):
        logger.debug("init")

        super(GLSliceWidget, self).__init__(parent, **kwargs)

        self.renderUpdate = True
        self.parent = parent

        self.setAcceptDrops(True)

        self.texture_LUT = None
        self.setTransform(TransformModel())

        self.renderTimer = QtCore.QTimer(self)
        self.renderTimer.setInterval(50)
        self.renderTimer.timeout.connect(self.onRenderTimer)
        self.renderTimer.start()

        self.dataModel = None

        self.dataPos = 0
        self.slicePos = 0

        self.zoom_fac = 1.
        self.zoom_x = 0.5
        self.zoom_y = 0.5
        # the center in tex coords
        self.zoom_cx = 0.5
        self.zoom_cy = 0.5

        interpolation_vals = ("linear", "nearest")
        if not interpolation in interpolation_vals:
            raise KeyError("interpolation = '%s' not defined ,valid: %s" %
                           (interpolation, str(interpolation_vals)))

        self.interp = (interpolation == "linear")
        # self.refresh()

    def setModel(self, dataModel):
        logger.debug("setModel")

        self.dataModel = dataModel

        if self.dataModel:
            self.transform.setModel(dataModel)

            self.dataModel._dataSourceChanged.connect(self.dataSourceChanged)
            self.dataModel._dataPosChanged.connect(self.dataPosChanged)
            self._dataModelChanged.connect(self.dataModelChanged)
            self._dataModelChanged.emit()

    def setTransform(self, transform):
        self.transform = transform
        self.transform._transformChanged.connect(self.refresh)

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        for url in event.mimeData().urls():
            path = url.toLocalFile().toLocal8Bit().data()
            if self.dataModel:
                self.dataModel.loadFromPath(path, prefetchSize=self.N_PREFETCH)
            else:
                self.setModel(
                    DataModel.fromPath(path, prefetchSize=self.N_PREFETCH))

    def set_colormap(self, name):
        """arr should be of shape (N,3) and gives the rgb components of the colormap"""

        try:
            arr = spimagine.config.__COLORMAPDICT__[name]
            self.makeCurrent()
            self.texture_LUT = fillTexture2d(arr.reshape((1, ) + arr.shape),
                                             self.texture_LUT, self.interp)
        except:
            print("could not load colormap %s" % name)

    def set_colormap_rgb(self, color=[1., 1., 1.]):
        self._set_colormap_array(outer(linspace(0, 1., 255), np.array(color)))

    def _set_colormap_array(self, arr):
        """arr should be of shape (N,3) and gives the rgb components of the colormap"""

        self.makeCurrent()
        self.texture_LUT = fillTexture2d(arr.reshape((1, ) + arr.shape),
                                         self.texture_LUT, self.interp)
        self.refresh()

    def initializeGL(self):

        self.resized = True

        self.output = zeros((100, 100))

        logger.debug("initializeGL")

        self.programTex = QOpenGLShaderProgram()
        self.programTex.addShaderFromSourceCode(QOpenGLShader.Vertex,
                                                vertShaderTex)
        self.programTex.addShaderFromSourceCode(QOpenGLShader.Fragment,
                                                fragShaderTex)
        self.programTex.link()
        self.programTex.bind()
        logger.debug("GLSL programTex log:%s", self.programTex.log())

        glClearColor(0, 0, 0, 1.)

        self.texture = None

        self.quadCoord = np.array([[-1., -1., 0.], [1., -1., 0.], [1., 1., 0.],
                                   [1., 1., 0.], [-1., 1., 0.], [-1., -1.,
                                                                 0.]])

        self.quadCoordTex = np.array([[0, 0], [1., 0.], [1., 1.], [1., 1.],
                                      [0, 1.], [0, 0]])

        self.set_colormap(spimagine.config.__DEFAULTCOLORMAP__)

        glDisable(GL_DEPTH_TEST)
        glEnable(GL_BLEND)

        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

    def dataModelChanged(self):
        # if self.dataModel:
        #     self.transform.reset(amin(self.dataModel[0]),
        #                          amax(self.dataModel[0]),
        #                          self.dataModel.stackUnits())
        #

        self.refresh()

    def dataSourceChanged(self):
        # self.transform.reset(amin(self.dataModel[0]),
        #                      amax(self.dataModel[0]),
        #                      self.dataModel.stackUnits())
        self.refresh()

    def dataPosChanged(self, pos):
        self.dataPos = pos
        self.refresh()

    def refresh(self):
        # if self.parentWidget() and self.dataModel:
        #     self.parentWidget().setWindowTitle("SpImagine %s"%self.dataModel.name())
        self.renderUpdate = True

    def resizeGL(self, width, height):
        # height = max(10,height)

        self._viewport_width, self._viewport_height = width, height

        self.resized = True
        self.resetViewPort()

    def getDataWidthHeight(self):
        if not self.dataModel:
            return 1, 1

        dim = array(self.dataModel.size()[1:])[::-1].astype(np.float32)

        dim *= array(self.transform.stackUnits)

        if self.transform.sliceDim == 0:
            dim = dim[[2, 1]]
        elif self.transform.sliceDim == 1:
            dim = dim[[0, 2]]
        elif self.transform.sliceDim == 2:
            dim = dim[[0, 1]]

        w, h = dim[0], dim[1]

        fac = min(1. * self._viewport_width / w,
                  1. * self._viewport_height / h)

        return int(fac * w), int(fac * h)

    def resetViewPort(self):
        w, h = self.getDataWidthHeight()
        glViewport((self._viewport_width - w) // 2,
                   (self._viewport_height - h) // 2, w, h)

    def paintGL(self):

        self.makeCurrent()

        if not glCheckFramebufferStatus(
                GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE:
            return

        # hack
        if self.resized:
            self.resetViewPort()

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        if self.dataModel:
            # Draw the render texture
            self.programTex.bind()

            self.texture = fillTexture2d(self.output, self.texture,
                                         self.interp)

            glEnable(GL_TEXTURE_2D)
            glDisable(GL_DEPTH_TEST)

            self.programTex.enableAttributeArray("position")
            self.programTex.enableAttributeArray("texcoord")
            self.programTex.setAttributeArray("position", self.quadCoord)
            self.programTex.setAttributeArray(
                "texcoord",
                self.tex_coords_from_xyzoom(self.zoom_x, self.zoom_y,
                                            self.zoom_fac))

            glActiveTexture(GL_TEXTURE0)
            glBindTexture(GL_TEXTURE_2D, self.texture)
            self.programTex.setUniformValue("texture", 0)

            glActiveTexture(GL_TEXTURE1)
            glBindTexture(GL_TEXTURE_2D, self.texture_LUT)
            self.programTex.setUniformValue("texture_LUT", 1)

            glDrawArrays(GL_TRIANGLES, 0, len(self.quadCoord))

    def render(self):
        logger.debug("render")
        if self.dataModel:
            if self.transform.sliceDim == 0:
                out = fliplr(self.dataModel[self.transform.dataPos]
                             [:, :, self.transform.slicePos].T)
            elif self.transform.sliceDim == 1:
                out = self.dataModel[
                    self.transform.dataPos][:, self.transform.slicePos, :]
            elif self.transform.sliceDim == 2:
                out = self.dataModel[self.transform.dataPos][
                    self.transform.slicePos, :, :]

            min_out, max_out = self.transform.minVal, self.transform.maxVal

            if max_out > min_out:
                self.output = np.maximum(
                    0, (1. * (out - min_out) /
                        (max_out - min_out)))**self.transform.gamma
            else:
                self.output = np.zeros_like(out)

            logger.debug(
                "render: output range = %s" %
                ([amin(self.output), amax(self.output)]))

    def saveFrame(self, fName):
        """FIXME: scaling behaviour still hast to be implemented (e.g. after setGamma)"""
        logger.info("saving frame as %s", fName)

        self.render()
        self.paintGL()
        glFlush()
        self.grabFrameBuffer().save(fName)

    def onRenderTimer(self):
        if self.renderUpdate:
            self.render()
            self.renderUpdate = False
            self.updateGL()

    def tex_coords_from_xyzoom(self, x0, y0, zoom):
        """returns array of texccords corners when zoomed
        in onto x0,y0 \in [0,1]
        
        zoom == 1   --> fully zoomed out
        zoom == 0   --> fully zoomed in (to x0,y0)
        """

        q0 = create_quad_coords([0, 1, 0, 1])
        q1 = create_quad_coords([x0, x0, y0, y0])

        return zoom * q0 + (1. - zoom) * q1

    def getRelativeCoords(self, x0, y0):
        w, h = self.getDataWidthHeight()

        w = w * self.width() / self._viewport_width
        h = w * self.height() / self._viewport_height

        x = 2. * (x0 - .5 * (self.width() - w)) / w - 1
        y = 2. * (y0 - .5 * (self.height() - h)) / h - 1

        x = (x0 - .5 * (self.width() - w)) / w
        y = 1 - (y0 - .5 * (self.height() - h)) / h

        return x, y

    def mousePressEvent(self, event):
        super(GLSliceWidget, self).mousePressEvent(event)

        if event.buttons() == QtCore.Qt.LeftButton:
            self._x0, self._y0 = self.getRelativeCoords(event.x(), event.y())

    def mouseMoveEvent(self, event):

        if event.buttons() == QtCore.Qt.LeftButton:
            x, y = self.getRelativeCoords(event.x(), event.y())
            self.zoom_x += self.zoom_fac * (self._x0 - x)
            self.zoom_y += self.zoom_fac * (self._y0 - y)
            self._x0, self._y0 = x, y
            self.zoom_x, self.zoom_y = clip(self.zoom_x, 0,
                                            1), clip(self.zoom_y, 0, 1)

        self.refresh()

    def wheelEvent(self, event):
        # get the zoom factor

        # print self.zoom_x,self.zoom_y
        # x, y = self.getRelativeCoords(event.x(),event.y())
        # self.zoom_x , self.zoom_y = clip(x ,0,1), clip(y,0,1)

        self.zoom_fac *= 1.4**(-event.angleDelta().y() / 1000.)
        self.zoom_fac = clip(self.zoom_fac, 0, 1.)

        self.refresh()
Exemple #7
0
class GLWidget(QOpenGLWidget):

    clicked = pyqtSignal()

    PROGRAM_VERTEX_ATTRIBUTE, PROGRAM_TEXCOORD_ATTRIBUTE = range(2)

    vsrc = """
attribute highp vec4 vertex;
attribute mediump vec4 texCoord;
varying mediump vec4 texc;
uniform mediump mat4 matrix;
void main(void)
{
    gl_Position = matrix * vertex;
    texc = texCoord;
}
"""

    fsrc = """
uniform sampler2D texture;
varying mediump vec4 texc;
void main(void)
{
    gl_FragColor = texture2D(texture, texc.st);
}
"""

    coords = (((+1, -1, -1), (-1, -1, -1), (-1, +1, -1), (+1, +1, -1)),
              ((+1, +1, -1), (-1, +1, -1), (-1, +1, +1), (+1, +1, +1)),
              ((+1, -1, +1), (+1, -1, -1), (+1, +1, -1), (+1, +1, +1)),
              ((-1, -1, -1), (-1, -1, +1), (-1, +1, +1),
               (-1, +1, -1)), ((+1, -1, +1), (-1, -1, +1), (-1, -1, -1),
                               (+1, -1, -1)), ((-1, -1, +1), (+1, -1, +1),
                                               (+1, +1, +1), (-1, +1, +1)))

    def __init__(self, parent=None):
        super(GLWidget, self).__init__(parent)

        self.clearColor = QColor(Qt.black)
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.program = None

        self.lastPos = QPoint()

    def minimumSizeHint(self):
        """
        Define the minimum size of the widget
        """
        return QSize(50, 50)

    def sizeHint(self):
        """
        Define a default size for the widget
        """
        return QSize(200, 200)

    def rotateBy(self, xAngle, yAngle, zAngle):
        self.xRot += xAngle
        self.yRot += yAngle
        self.zRot += zAngle
        self.update()

    def setClearColor(self, color):
        self.clearColor = color
        self.update()

    def initializeGL(self):
        self.gl = self.context().versionFunctions()
        self.gl.initializeOpenGLFunctions()

        self.makeObject()

        self.gl.glEnable(self.gl.GL_DEPTH_TEST)
        self.gl.glEnable(self.gl.GL_CULL_FACE)

        vshader = QOpenGLShader(QOpenGLShader.Vertex, self)
        vshader.compileSourceCode(self.vsrc)

        fshader = QOpenGLShader(QOpenGLShader.Fragment, self)
        fshader.compileSourceCode(self.fsrc)

        self.program = QOpenGLShaderProgram()
        self.program.addShader(vshader)
        self.program.addShader(fshader)
        self.program.bindAttributeLocation('vertex',
                                           self.PROGRAM_VERTEX_ATTRIBUTE)
        self.program.bindAttributeLocation('texCoord',
                                           self.PROGRAM_TEXCOORD_ATTRIBUTE)
        self.program.link()

        self.program.bind()
        self.program.setUniformValue('texture', 0)

        self.program.enableAttributeArray(self.PROGRAM_VERTEX_ATTRIBUTE)
        self.program.enableAttributeArray(self.PROGRAM_TEXCOORD_ATTRIBUTE)
        self.program.setAttributeArray(self.PROGRAM_VERTEX_ATTRIBUTE,
                                       self.vertices)
        self.program.setAttributeArray(self.PROGRAM_TEXCOORD_ATTRIBUTE,
                                       self.texCoords)

    def paintGL(self):
        self.gl.glClearColor(self.clearColor.redF(), self.clearColor.greenF(),
                             self.clearColor.blueF(), self.clearColor.alphaF())
        self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT
                        | self.gl.GL_DEPTH_BUFFER_BIT)

        m = QMatrix4x4()
        m.ortho(-0.5, 0.5, 0.5, -0.5, 4.0, 15.0)
        m.translate(0.0, 0.0, -10.0)

        self.program.setUniformValue('matrix', m)

        self.texture.bind()
        self.gl.glDrawArrays(self.gl.GL_TRIANGLE_FAN, 0, 4)

    def resizeGL(self, width, height):
        side = min(width, height)
        self.gl.glViewport((width - side) // 2, (height - side) // 2, side,
                           side)

    def makeObject(self):
        self.texCoords = [(True, True), (False, True), (False, False),
                          (True, False)]
        self.vertices = [(0.5, -0.5, -0.5), (-0.5, -0.5, -0.5),
                         (-0.5, 0.5, -0.5), (0.5, 0.5, -0.5)]

        my_movie = QImage('/Users/reno/Dropbox/media/cloudy.png')
        self.texture = QOpenGLTexture(my_movie.mirrored())
class AkiraRenderWindow(OpenGLWindow):

    def __init__(self):
        super(AkiraRenderWindow, self).__init__()

        self.m_program = 0
        self.m_frame = 0.0

        self.m_vertex = 0
        self.m_vertices = []
        self.m_color = 0
        self.m_colors = []
        self.m_offset = 0
        self.m_offsets = 0

        self.m_vao = None

    def initialize(self):

        self.create_shader()
        self.create_vao()

    def create_shader(self):
        self.m_program = QOpenGLShaderProgram(self)

        self.m_program.addShaderFromSourceFile(QOpenGLShader.Vertex, "shaders/chapter2.vs.glsl")
        self.m_program.addShaderFromSourceFile(QOpenGLShader.Fragment, "shaders/chapter2.fs.glsl")

        self.m_program.link()

        self.m_vertex = self.m_program.attributeLocation("m_vertex")
        self.m_offset = self.m_program.attributeLocation("m_offset")
        self.m_color = self.m_program.attributeLocation("m_color")

        return self

    def create_vao(self):

        vertex_array_object = GL.glGenVertexArrays(1)
        GL.glBindVertexArray(vertex_array_object)

        vertex_buffer = GL.glGenBuffers(1)
        GL.glBindBuffer(GL.GL_ARRAY_BUFFER, vertex_buffer)

        #using PyQt shader program instead
        GL.glEnableVertexAttribArray(self.m_vertex)
        GL.glEnableVertexAttribArray(self.m_color)
        self.m_vao = vertex_array_object
        return self

    def render(self):

        ratio = int(self.devicePixelRatio().real)
        GL.glViewport(0, 0, self.width()*ratio, self.height()*ratio)
        GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT)

        self.m_offsets = QVector4D(sin(self.m_frame/20)*0.5, cos(self.m_frame/20)*0.5, 0.0, 0.0)

        self.m_vertices = [(0.25, -0.25, 0, 1.0),
                           (-0.25, -0.25, 0, 1.0),
                           (0.25,  0.25, 0, 1.0)]

        self.m_colors = [(0.0, 0.0, 1.0, 1.0),
                         (1.0, 0.0, 0.0, 1.0),
                         (0.0, 1.0, 0.0, 1.0)]

        self.m_program.setAttributeValue(self.m_offset, self.m_offsets)
        self.m_program.setAttributeArray(self.m_vertex, self.m_vertices)
        self.m_program.setAttributeArray(self.m_color, self.m_colors)

        self.m_program.bind()

        GL.glDrawArrays(GL.GL_TRIANGLES, 0, 3)
        self.m_program.release()

        self.m_frame += 1
class TriangleUnderlayRenderer(QObject):
    def __init__(self, parent=None):
        super(TriangleUnderlayRenderer, self).__init__(parent)
        self._shader_program = None
        self._viewport_size = QSize()
        self._window = None
        self._camera = Camera()

        self._perspective_projection_matrix = perspective_projection(
            45.0, 4.0 / 3.0, 0.001, 100.0)

        self._orthographic_projection_matrix = orthographic_projection(
            640.0, 480.0, 0.001, 100.0)

        self._model_matrix = np.identity(4)

        self._projection_type = 0
        self._projection_matrix = self._perspective_projection_matrix

        self._theta = 0.0

    def set_theta(self, theta):
        self._theta = theta

    # around y axis
    def build_rotation_matrix(self):
        m = np.identity(4)
        m[0][0] = np.cos(np.radians(self._theta))
        m[0][2] = np.sin(np.radians(self._theta))
        m[2][0] = -np.sin(np.radians(self._theta))
        m[2][2] = np.cos(np.radians(self._theta))
        return m

    @pyqtSlot(int)
    def setProjectionType(self, t):
        if t != self._projection_type:
            self._projection_type = t

    @pyqtSlot()
    def paint(self):
        # for Darwin, it's a must
        if pf.uname().system == 'Darwin':
            global GL
            GL = self._window.openglContext().versionFunctions()

        w = self._viewport_size.width()
        h = self._viewport_size.height()

        GL.glViewport(0, 0, int(w), int(h))

        if self._shader_program is None:
            self._shader_program = QOpenGLShaderProgram()
            self._shader_program.addShaderFromSourceFile(
                QOpenGLShader.Vertex, 'shaders/OpenGL_2_1/vertex.glsl')
            self._shader_program.addShaderFromSourceFile(
                QOpenGLShader.Fragment, 'shaders/OpenGL_2_1/fragment.glsl')
            self._shader_program.bindAttributeLocation('position', 0)
            self._shader_program.bindAttributeLocation('color', 1)
            self._shader_program.link()

        self._shader_program.bind()
        self._shader_program.enableAttributeArray(0)
        self._shader_program.enableAttributeArray(1)

        self._shader_program.setAttributeArray(0, positions)
        self._shader_program.setAttributeArray(1, colors)

        if self._projection_type == 0:
            self._projection_matrix = self._perspective_projection_matrix
        elif self._projection_type == 1:
            self._projection_matrix = self._orthographic_projection_matrix

        self._model_matrix = self.build_rotation_matrix()

        self._shader_program.setUniformValue(
            'model_matrix', QMatrix4x4(self._model_matrix.flatten().tolist()))

        self._shader_program.setUniformValue(
            'view_matrix',
            QMatrix4x4(self._camera.get_view_matrix().flatten().tolist()))

        self._shader_program.setUniformValue(
            'projection_matrix',
            QMatrix4x4(self._projection_matrix.flatten().tolist()))

        GL.glClearColor(0.2, 0.2, 0.2, 1)
        GL.glEnable(GL.GL_DEPTH_TEST)
        GL.glClear(GL.GL_COLOR_BUFFER_BIT)
        GL.glDrawArrays(GL.GL_TRIANGLES, 0, 3)

        self._shader_program.disableAttributeArray(0)
        self._shader_program.disableAttributeArray(1)

        self._shader_program.release()

        # Restore the OpenGL state for QtQuick rendering
        self._window.resetOpenGLState()
        self._window.update()

    def set_viewport_size(self, size):
        self._viewport_size = size

    def set_window(self, window):
        self._window = window

    def set_projection_matrix(self):
        # Need to be set every time we change the size of the window
        self._perspective_projection_matrix = perspective_projection(
            45.0,
            self._viewport_size.width() / self._viewport_size.height(), 0.001,
            100.0)

        self._orthographic_projection_matrix = orthographic_projection(
            self._viewport_size.width(), self._viewport_size.height(), 0.001,
            100.0)
class ModelUnderlayRenderer(QObject):
    def __init__(self, parent=None):
        super(ModelUnderlayRenderer, self).__init__(parent)

        self._cube_shader = None
        self._sphere_shader = None
        self._viewport_size = QSize()
        self._window = None
        self._camera = Camera()

        self._perspective_projection_matrix = None
        self._orthographic_projection_matrix = None

        self._model_matrix = np.identity(4)

        self._projection_type = 0
        self._projection_matrix = perspective_projection(
            45.0, 640.0 / 480.0, 0.001, 1000.0)

        self._index_buffer = -1

        # keep track of the objects in the scene
        self._cube_model = Cube()
        self._sphere_model = Sphere()

        self._models = dict()
        self._models[self._cube_model] = []
        self._models[self._sphere_model] = []

    @pyqtSlot()
    def paint(self):
        # for Darwin, it's a must
        if pf.uname().system == 'Darwin':
            global GL
            GL = self._window.openglContext().versionFunctions()

        w = self._viewport_size.width()
        h = self._viewport_size.height()

        GL.glViewport(0, 0, int(w), int(h))
        GL.glClearColor(0.1, 0.1, 0.1, 1)
        GL.glEnable(GL.GL_DEPTH_TEST)
        GL.glClear(GL.GL_COLOR_BUFFER_BIT)
        GL.glClear(GL.GL_DEPTH_BUFFER_BIT)
        #
        # vertices_block = np.vstack((self._cube_model.vertices, self._sphere_model.vertices))
        # colors_block = np.vstack((self._cube_model.colors, self._sphere_model))
        #
        # if len(self._objects) > 1:
        # 	for v in self._vertices[1:]:
        # 		vertices_block = np.vstack((vertices_block, v))
        # 	for idx, c in enumerate(self._colors[1:]):
        # 		if not c:
        # 			c = [[0.6, 0.6, 0.7] for i in range(len(self._vertices[idx]))]
        # 		colors_block = np.vstack((colors_block, c))
        # 	for i in self._indices[1:]:
        # 		indices_block = np.hstack((indices_block, i))
        view_matrix = np.identity(4)
        view_matrix[2][3] = -30

        if self._cube_shader is None:
            self._cube_shader = QOpenGLShaderProgram()
            self._cube_shader.addShaderFromSourceFile(
                QOpenGLShader.Vertex, 'shaders/OpenGL_2_1/vertex.glsl')
            self._cube_shader.addShaderFromSourceFile(
                QOpenGLShader.Fragment, 'shaders/OpenGL_2_1/fragment.glsl')
            self._cube_shader.bindAttributeLocation('position', 0)
            self._cube_shader.bindAttributeLocation('color', 1)
            self._cube_shader.link()

        self._cube_shader.bind()
        self._cube_shader.enableAttributeArray(0)
        self._cube_shader.enableAttributeArray(1)
        self._cube_shader.setAttributeArray(0,
                                            self._cube_model.vertices.tolist())
        self._cube_shader.setAttributeArray(1,
                                            self._cube_model.colors.tolist())
        # view_matrix = self._camera.get_view_matrix()
        self._cube_shader.setUniformValue(
            'view_matrix',
            QMatrix4x4(view_matrix.flatten().tolist()).transposed())
        self._cube_shader.setUniformValue(
            'projection_matrix',
            QMatrix4x4(
                self._projection_matrix.flatten().tolist()).transposed())

        if self._cube_model in self._models.keys():
            for entity in self._models[self._cube_model]:
                m = create_transformation_matrix(entity.position,
                                                 entity.rotation, entity.scale)
                self._cube_shader.setUniformValue(
                    'model_matrix', QMatrix4x4(m.flatten().tolist()))
                GL.glDrawElements(GL.GL_TRIANGLES,
                                  len(self._cube_model.indices),
                                  GL.GL_UNSIGNED_INT,
                                  self._cube_model.indices.tolist())

        self._cube_shader.disableAttributeArray(0)
        self._cube_shader.disableAttributeArray(1)
        self._cube_shader.release()

        if self._sphere_shader is None:
            self._sphere_shader = QOpenGLShaderProgram()
            self._sphere_shader.addShaderFromSourceFile(
                QOpenGLShader.Vertex, 'shaders/OpenGL_2_1/vertex.glsl')
            self._sphere_shader.addShaderFromSourceFile(
                QOpenGLShader.Fragment, 'shaders/OpenGL_2_1/fragment.glsl')
            self._sphere_shader.bindAttributeLocation('position', 0)
            self._sphere_shader.bindAttributeLocation('color', 1)
            self._sphere_shader.link()

        self._sphere_shader.bind()
        self._sphere_shader.enableAttributeArray(0)
        self._sphere_shader.enableAttributeArray(1)
        self._sphere_shader.setAttributeArray(
            0, self._sphere_model.vertices.tolist())
        self._sphere_shader.setAttributeArray(
            1, self._sphere_model.colors.tolist())
        self._sphere_shader.setUniformValue(
            'view_matrix',
            QMatrix4x4(view_matrix.flatten().tolist()).transposed())
        self._sphere_shader.setUniformValue(
            'projection_matrix',
            QMatrix4x4(
                self._projection_matrix.flatten().tolist()).transposed())

        if self._sphere_model in self._models.keys():
            for entity in self._models[self._sphere_model]:
                m = create_transformation_matrix(entity.position,
                                                 entity.rotation, entity.scale)
                self._cube_shader.setUniformValue(
                    'model_matrix', QMatrix4x4(m.flatten().tolist()))
                GL.glDrawElements(GL.GL_TRIANGLES,
                                  len(self._sphere_model.indices),
                                  GL.GL_UNSIGNED_INT,
                                  self._sphere_model.indices.tolist())
        self._sphere_shader.disableAttributeArray(0)
        self._sphere_shader.disableAttributeArray(1)
        self._sphere_shader.release()

        # def build_rotation_matrix (t):
        # 	m = np.identity(4)
        # 	m[0][0] = np.cos(np.radians(t))
        # 	m[0][2] = np.sin(np.radians(t))
        # 	m[2][0] = -np.sin(np.radians(t))
        # 	m[2][2] = np.cos(np.radians(t))
        # 	return m
        #
        # global theta
        # theta += 1
        # self._model_matrix = build_rotation_matrix(theta)
        # self._model_matrix[2][3] = -3

        # Restore the OpenGL state for QtQuick rendering
        self._window.resetOpenGLState()
        self._window.update()

    def set_viewport_size(self, size):
        self._viewport_size = size

    def set_window(self, window):
        self._window = window

    def set_projection_matrix(self):
        # Need to be set every time we change the size of the window
        self._projection_matrix = perspective_projection(
            45.0,
            self._window.width() / self._window.height(), 0.001, 1000.0)

    def move_model(self, val):
        self._model_matrix[2][3] += val

    def move_camera(self):
        pass

    def add_geometry(self, geo_enum):
        if geo_enum == 0:
            self._models[self._cube_model].append(
                Entity(
                    self._cube_model,
                    np.array([
                        random.uniform(-3.0, 3.0),
                        random.uniform(-3.0, 3.0),
                        random.uniform(-20.0, -10.0)
                    ]),
                    np.array([
                        random.uniform(-45.0, 45.0),
                        random.uniform(-45.0, 45.0),
                        random.uniform(-45.0, 45.0)
                    ]), np.array([1.0, 1.0, 1.0])))
        elif geo_enum == 1:
            self._models[self._sphere_model].append(
                Entity(
                    self._sphere_model,
                    np.array([
                        random.uniform(-3.0, 3.0),
                        random.uniform(-3.0, 3.0),
                        random.uniform(-20.0, -10.0)
                    ]),
                    np.array([
                        random.uniform(-30.0, 30.0),
                        random.uniform(-30.0, 30.0),
                        random.uniform(-30.0, 30.0)
                    ]), np.array([1.0, 1.0, 1.0])))
        else:
            return

    def delete_geometry(self, geo_enum):
        if geo_enum == 0:
            if self._models[self._cube_model]:
                self._models[self._cube_model].pop()
        elif geo_enum == 1:
            if self._models[self._sphere_model]:
                self._models[self._sphere_model].pop()

    def change_random_cube_color(self):
        tmp = self._models[self._cube_model]
        self._models.pop(self._cube_model)
        self._cube_model = Cube()
        self._models[self._cube_model] = tmp

    def change_random_sphere_color(self):
        tmp = self._models[self._sphere_model]
        self._models.pop(self._sphere_model)
        self._sphere_model = Sphere()
        self._models[self._sphere_model] = tmp
Exemple #11
0
class GLSliceWidget(QtOpenGL.QGLWidget):
    _dataModelChanged = QtCore.pyqtSignal()

    def __init__(self, parent=None, interpolation="linear", **kwargs):
        logger.debug("init")

        super(GLSliceWidget, self).__init__(parent, **kwargs)

        self.renderUpdate = True
        self.parent = parent

        self.setAcceptDrops(True)

        self.texture_LUT = None
        self.setTransform(TransformModel())

        self.renderTimer = QtCore.QTimer(self)
        self.renderTimer.setInterval(50)
        self.renderTimer.timeout.connect(self.onRenderTimer)
        self.renderTimer.start()

        self.dataModel = None

        self.dataPos = 0
        self.slicePos = 0

        self.zoom_fac = 1.
        self.zoom_x = 0.5
        self.zoom_y = 0.5
        # the center in tex coords
        self.zoom_cx = 0.5
        self.zoom_cy = 0.5

        interpolation_vals = ("linear", "nearest")
        if not interpolation in interpolation_vals:
            raise KeyError("interpolation = '%s' not defined ,valid: %s" % (interpolation, str(interpolation_vals)))

        self.interp = (interpolation =="linear")
        # self.refresh()

    def setModel(self, dataModel):
        logger.debug("setModel")

        self.dataModel = dataModel

        if self.dataModel:
            self.transform.setModel(dataModel)

            self.dataModel._dataSourceChanged.connect(self.dataSourceChanged)
            self.dataModel._dataPosChanged.connect(self.dataPosChanged)
            self._dataModelChanged.connect(self.dataModelChanged)
            self._dataModelChanged.emit()

    def setTransform(self, transform):
        self.transform = transform
        self.transform._transformChanged.connect(self.refresh)

    def dragEnterEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        for url in event.mimeData().urls():
            path = url.toLocalFile().toLocal8Bit().data()
            if self.dataModel:
                self.dataModel.loadFromPath(path, prefetchSize=self.N_PREFETCH)
            else:
                self.setModel(DataModel.fromPath(path, prefetchSize=self.N_PREFETCH))

    def set_colormap(self, name):
        """arr should be of shape (N,3) and gives the rgb components of the colormap"""

        try:
            arr = spimagine.config.__COLORMAPDICT__[name]
            self.makeCurrent()
            self.texture_LUT = fillTexture2d(arr.reshape((1,) + arr.shape), self.texture_LUT, self.interp)
        except:
            print("could not load colormap %s" % name)

    def set_colormap_rgb(self, color=[1., 1., 1.]):
        self._set_colormap_array(outer(linspace(0, 1., 255), np.array(color)))

    def _set_colormap_array(self, arr):
        """arr should be of shape (N,3) and gives the rgb components of the colormap"""

        self.makeCurrent()
        self.texture_LUT = fillTexture2d(arr.reshape((1,) + arr.shape), self.texture_LUT, self.interp)
        self.refresh()

    def initializeGL(self):

        self.resized = True

        self.output = zeros((100, 100))

        logger.debug("initializeGL")

        self.programTex = QOpenGLShaderProgram()
        self.programTex.addShaderFromSourceCode(QOpenGLShader.Vertex, vertShaderTex)
        self.programTex.addShaderFromSourceCode(QOpenGLShader.Fragment, fragShaderTex)
        self.programTex.link()
        self.programTex.bind()
        logger.debug("GLSL programTex log:%s", self.programTex.log())

        glClearColor(0, 0, 0, 1.)

        self.texture = None

        self.quadCoord = np.array([[-1., -1., 0.],
                                   [1., -1., 0.],
                                   [1., 1., 0.],
                                   [1., 1., 0.],
                                   [-1., 1., 0.],
                                   [-1., -1., 0.]])

        self.quadCoordTex = np.array([[0, 0],
                                      [1., 0.],
                                      [1., 1.],
                                      [1., 1.],
                                      [0, 1.],
                                      [0, 0]])

        self.set_colormap(spimagine.config.__DEFAULTCOLORMAP__)

        glDisable(GL_DEPTH_TEST)
        glEnable(GL_BLEND)

        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

    def dataModelChanged(self):
        # if self.dataModel:
        #     self.transform.reset(amin(self.dataModel[0]),
        #                          amax(self.dataModel[0]),
        #                          self.dataModel.stackUnits())
        #

        self.refresh()

    def dataSourceChanged(self):
        # self.transform.reset(amin(self.dataModel[0]),
        #                      amax(self.dataModel[0]),
        #                      self.dataModel.stackUnits())
        self.refresh()

    def dataPosChanged(self, pos):
        self.dataPos = pos
        self.refresh()

    def refresh(self):
        # if self.parentWidget() and self.dataModel:
        #     self.parentWidget().setWindowTitle("SpImagine %s"%self.dataModel.name())
        self.renderUpdate = True

    def resizeGL(self, width, height):
        # height = max(10,height)

        self._viewport_width, self._viewport_height = width, height

        self.resized = True
        self.resetViewPort()

    def getDataWidthHeight(self):
        if not self.dataModel:
            return 1, 1

        dim = array(self.dataModel.size()[1:])[::-1].astype(np.float32)

        dim *= array(self.transform.stackUnits)

        if self.transform.sliceDim == 0:
            dim = dim[[2, 1]]
        elif self.transform.sliceDim == 1:
            dim = dim[[0, 2]]
        elif self.transform.sliceDim == 2:
            dim = dim[[0, 1]]

        w, h = dim[0], dim[1]

        fac = min(1. * self._viewport_width / w, 1. * self._viewport_height / h)

        return int(fac * w), int(fac * h)

    def resetViewPort(self):
        w, h = self.getDataWidthHeight()
        glViewport((self._viewport_width - w) // 2, (self._viewport_height - h) // 2, w, h)

    def paintGL(self):

        self.makeCurrent()

        if not glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE:
            return

        # hack
        if self.resized:
            self.resetViewPort()

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)

        if self.dataModel:
            # Draw the render texture
            self.programTex.bind()

            self.texture = fillTexture2d(self.output, self.texture, self.interp)

            glEnable(GL_TEXTURE_2D)
            glDisable(GL_DEPTH_TEST)

            self.programTex.enableAttributeArray("position")
            self.programTex.enableAttributeArray("texcoord")
            self.programTex.setAttributeArray("position", self.quadCoord)
            self.programTex.setAttributeArray("texcoord",
                                              self.tex_coords_from_xyzoom(self.zoom_x, self.zoom_y, self.zoom_fac))

            glActiveTexture(GL_TEXTURE0)
            glBindTexture(GL_TEXTURE_2D, self.texture)
            self.programTex.setUniformValue("texture", 0)

            glActiveTexture(GL_TEXTURE1)
            glBindTexture(GL_TEXTURE_2D, self.texture_LUT)
            self.programTex.setUniformValue("texture_LUT", 1)

            glDrawArrays(GL_TRIANGLES, 0, len(self.quadCoord))

    def render(self):
        logger.debug("render")
        if self.dataModel:
            if self.transform.sliceDim == 0:
                out = fliplr(self.dataModel[self.transform.dataPos][:, :, self.transform.slicePos].T)
            elif self.transform.sliceDim == 1:
                out = self.dataModel[self.transform.dataPos][:, self.transform.slicePos, :]
            elif self.transform.sliceDim == 2:
                out = self.dataModel[self.transform.dataPos][self.transform.slicePos, :, :]

            min_out, max_out = self.transform.minVal, self.transform.maxVal

            if max_out > min_out:
                self.output = np.maximum(0,(1. * (out - min_out) / (max_out - min_out))) ** self.transform.gamma
            else:
                self.output = np.zeros_like(out)

            logger.debug("render: output range = %s" % ([amin(self.output), amax(self.output)]))

    def saveFrame(self, fName):
        """FIXME: scaling behaviour still hast to be implemented (e.g. after setGamma)"""
        logger.info("saving frame as %s", fName)

        self.render()
        self.paintGL()
        glFlush()
        self.grabFrameBuffer().save(fName)

    def onRenderTimer(self):
        if self.renderUpdate:
            self.render()
            self.renderUpdate = False
            self.updateGL()

    def tex_coords_from_xyzoom(self, x0, y0, zoom):
        """returns array of texccords corners when zoomed
        in onto x0,y0 \in [0,1]
        
        zoom == 1   --> fully zoomed out
        zoom == 0   --> fully zoomed in (to x0,y0)
        """

        q0 = create_quad_coords([0, 1, 0, 1])
        q1 = create_quad_coords([x0, x0, y0, y0])

        return zoom * q0 + (1. - zoom) * q1

    def getRelativeCoords(self, x0, y0):
        w, h = self.getDataWidthHeight()

        w = w * self.width() / self._viewport_width
        h = w * self.height() / self._viewport_height

        x = 2. * (x0 - .5 * (self.width() - w)) / w - 1
        y = 2. * (y0 - .5 * (self.height() - h)) / h - 1

        x = (x0 - .5 * (self.width() - w)) / w
        y = 1 - (y0 - .5 * (self.height() - h)) / h

        return x, y

    def mousePressEvent(self, event):
        super(GLSliceWidget, self).mousePressEvent(event)

        if event.buttons() == QtCore.Qt.LeftButton:
            self._x0, self._y0 = self.getRelativeCoords(event.x(), event.y())

    def mouseMoveEvent(self, event):

        if event.buttons() == QtCore.Qt.LeftButton:
            x, y = self.getRelativeCoords(event.x(), event.y())
            self.zoom_x += self.zoom_fac * (self._x0 - x)
            self.zoom_y += self.zoom_fac * (self._y0 - y)
            self._x0, self._y0 = x, y
            self.zoom_x, self.zoom_y = clip(self.zoom_x, 0, 1), clip(self.zoom_y, 0, 1)

        self.refresh()

    def wheelEvent(self, event):
        # get the zoom factor

        # print self.zoom_x,self.zoom_y
        # x, y = self.getRelativeCoords(event.x(),event.y())
        # self.zoom_x , self.zoom_y = clip(x ,0,1), clip(y,0,1)



        self.zoom_fac *= 1.4 ** (-event.angleDelta().y() / 1000.)
        self.zoom_fac = clip(self.zoom_fac, 0, 1.)

        self.refresh()
Exemple #12
0
class MyWidget(QtOpenGL.QGLWidget):
    def __init__(self, parent = None):
        super(MyWidget, self).__init__(parent)

        self.quadCoord = np.array([[-1., -1., 0.],
                                   [1., -1., 0.],
                                   [1., 1., 0.],
                                   [1., 1., 0.],
                                   [-1., 1., 0.],
                                   [-1., -1., 0.]])

        self.quadCoordTex = np.array([[0, 0],
                                      [1., 0.],
                                      [1., 1.],
                                      [1., 1.],
                                      [0, 1.],
                                      [0, 0]])

    def initializeGL(self):
        GL.glClearColor(1.0, 0.0, 0.0, 1.0)
        GL.glEnable(GL.GL_BLEND)
        GL.glBlendFunc (GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
        GL.glClear(GL.GL_COLOR_BUFFER_BIT)

        print("OpenGL.GL: " + str(GL.glGetString(GL.GL_VERSION)))
        print("GL.GLSL: " + str(GL.glGetString(GL.GL_SHADING_LANGUAGE_VERSION)))
        print("OpenGL ATTRIBUTES:\n",", ".join(d for d in dir(GL) if d.startswith("GL_")))

        self.program = QOpenGLShaderProgram()
        self.program.addShaderFromSourceCode(QOpenGLShader.Vertex, """#version 120
        attribute vec2 position;
        attribute vec2 texcoord;
        varying vec2 mytexcoord;
        void main() {
            gl_Position = vec4(position, 0., 1.0);
            mytexcoord = texcoord;
        }""")

        self.program.addShaderFromSourceCode(QOpenGLShader.Fragment, """#version 120
        uniform sampler2D texture;
        varying vec2 mytexcoord;
        void main() {
            
            gl_FragColor = texture2D(texture,mytexcoord);
        }""")
        print(self.program.log())
        self.program.link()

        self.texture = fillTexture2d(np.outer(np.linspace(0, 1, 128), np.ones(128)))

    def paintGL(self):
        #GL.glClear(GL.GL_COLOR_BUFFER_BIT)
        self.program.bind()

        self.program.enableAttributeArray("position")
        self.program.enableAttributeArray("texcoord")
        self.program.setAttributeArray("position", self.quadCoord)
        self.program.setAttributeArray("texcoord", self.quadCoordTex)

        GL.glActiveTexture(GL.GL_TEXTURE0)
        GL.glBindTexture(GL.GL_TEXTURE_2D, self.texture)
        self.program.setUniformValue("texture", 0)

        GL.glDrawArrays(GL.GL_TRIANGLES, 0, len(self.quadCoord))
Exemple #13
0
class GLWidget(QOpenGLWidget):

    clicked = pyqtSignal()

    PROGRAM_VERTEX_ATTRIBUTE, PROGRAM_TEXCOORD_ATTRIBUTE = range(2)

    vsrc = """
attribute highp vec4 vertex;
attribute mediump vec4 texCoord;
varying mediump vec4 texc;
uniform mediump mat4 matrix;
void main(void)
{
    gl_Position = matrix * vertex;
    texc = texCoord;
}
"""

    fsrc = """
uniform sampler2D texture;
varying mediump vec4 texc;
void main(void)
{
    gl_FragColor = texture2D(texture, texc.st);
}
"""

    coords = (
        (( +1, -1, -1 ), ( -1, -1, -1 ), ( -1, +1, -1 ), ( +1, +1, -1 )),
        (( +1, +1, -1 ), ( -1, +1, -1 ), ( -1, +1, +1 ), ( +1, +1, +1 )),
        (( +1, -1, +1 ), ( +1, -1, -1 ), ( +1, +1, -1 ), ( +1, +1, +1 )),
        (( -1, -1, -1 ), ( -1, -1, +1 ), ( -1, +1, +1 ), ( -1, +1, -1 )),
        (( +1, -1, +1 ), ( -1, -1, +1 ), ( -1, -1, -1 ), ( +1, -1, -1 )),
        (( -1, -1, +1 ), ( +1, -1, +1 ), ( +1, +1, +1 ), ( -1, +1, +1 ))
    )

    def __init__(self, parent=None):
        super(GLWidget, self).__init__(parent)

        self.clearColor = QColor(Qt.black)
        self.xRot = 0
        self.yRot = 0
        self.zRot = 0
        self.program = None

        self.lastPos = QPoint()

    def minimumSizeHint(self):
        return QSize(50, 50)

    def sizeHint(self):
        return QSize(200, 200)

    def rotateBy(self, xAngle, yAngle, zAngle):
        self.xRot += xAngle
        self.yRot += yAngle
        self.zRot += zAngle
        self.update()

    def setClearColor(self, color):
        self.clearColor = color
        self.update()

    def initializeGL(self):
        self.gl = self.context().versionFunctions()
        self.gl.initializeOpenGLFunctions()

        self.makeObject()

        self.gl.glEnable(self.gl.GL_DEPTH_TEST)
        self.gl.glEnable(self.gl.GL_CULL_FACE)

        vshader = QOpenGLShader(QOpenGLShader.Vertex, self)
        vshader.compileSourceCode(self.vsrc)

        fshader = QOpenGLShader(QOpenGLShader.Fragment, self)
        fshader.compileSourceCode(self.fsrc)

        self.program = QOpenGLShaderProgram()
        self.program.addShader(vshader)
        self.program.addShader(fshader)
        self.program.bindAttributeLocation('vertex',
                self.PROGRAM_VERTEX_ATTRIBUTE)
        self.program.bindAttributeLocation('texCoord',
                self.PROGRAM_TEXCOORD_ATTRIBUTE)
        self.program.link()

        self.program.bind()
        self.program.setUniformValue('texture', 0)

        self.program.enableAttributeArray(self.PROGRAM_VERTEX_ATTRIBUTE)
        self.program.enableAttributeArray(self.PROGRAM_TEXCOORD_ATTRIBUTE)
        self.program.setAttributeArray(self.PROGRAM_VERTEX_ATTRIBUTE,
                self.vertices)
        self.program.setAttributeArray(self.PROGRAM_TEXCOORD_ATTRIBUTE,
                self.texCoords)

    def paintGL(self):
        self.gl.glClearColor(self.clearColor.redF(), self.clearColor.greenF(),
                self.clearColor.blueF(), self.clearColor.alphaF())
        self.gl.glClear(
                self.gl.GL_COLOR_BUFFER_BIT | self.gl.GL_DEPTH_BUFFER_BIT)

        m = QMatrix4x4()
        m.ortho(-0.5, 0.5, 0.5, -0.5, 4.0, 15.0)
        m.translate(0.0, 0.0, -10.0)
        m.rotate(self.xRot / 16.0, 1.0, 0.0, 0.0)
        m.rotate(self.yRot / 16.0, 0.0, 1.0, 0.0)
        m.rotate(self.zRot / 16.0, 0.0, 0.0, 1.0)

        self.program.setUniformValue('matrix', m)

        for i, texture in enumerate(self.textures):
            texture.bind()
            self.gl.glDrawArrays(self.gl.GL_TRIANGLE_FAN, i * 4, 4)

    def resizeGL(self, width, height):
        side = min(width, height)
        self.gl.glViewport((width - side) // 2, (height - side) // 2, side,
                side)

    def mousePressEvent(self, event):
        self.lastPos = event.pos()

    def mouseMoveEvent(self, event):
        dx = event.x() - self.lastPos.x()
        dy = event.y() - self.lastPos.y()

        if event.buttons() & Qt.LeftButton:
            self.rotateBy(8 * dy, 8 * dx, 0)
        elif event.buttons() & Qt.RightButton:
            self.rotateBy(8 * dy, 0, 8 * dx)

        self.lastPos = event.pos()

    def mouseReleaseEvent(self, event):
        self.clicked.emit()

    def makeObject(self):
        self.textures = []
        self.texCoords = []
        self.vertices = []

        root = QFileInfo(__file__).absolutePath()

        for i in range(6):
            self.textures.append(
                    QOpenGLTexture(
                            QImage(root + ('/images/side%d.png' % (i + 1))).mirrored()))

            for j in range(4):
                self.texCoords.append(((j == 0 or j == 3), (j == 0 or j == 1)))

                x, y, z = self.coords[i][j]
                self.vertices.append((0.2 * x, 0.2 * y, 0.2 * z))
Exemple #14
0
class SquircleRenderer(QObject):  #QOpenGLFunctions
    """docstring for SquircleRenderer"""
    def __init__(self, parent=None):
        super(SquircleRenderer, self).__init__(parent)
        self.m_t = 0.0
        self.m_program = None
        self.m_viewportSize = QSize()

    def setT(self, t):
        self.m_t = t

    def setViewportSize(self, size):
        self.m_viewportSize = size

    def setWin(self, win):
        self.win = win

        ver = QOpenGLVersionProfile()
        ver.setVersion(2, 1)

        self.m_context = self.win.openglContext()
        self.gl = self.m_context.versionFunctions(ver)

    @pyqtSlot()
    def paint(self):
        if not self.m_program:
            self.gl.initializeOpenGLFunctions()

            self.m_program = QOpenGLShaderProgram(self)
            self.m_program.addShaderFromSourceCode(
                QOpenGLShader.Vertex, "attribute highp vec4 vertices;"
                "varying highp vec2 coords;"
                "void main() {"
                "    gl_Position = vertices;"
                "    coords = vertices.xy;"
                "}")
            self.m_program.addShaderFromSourceCode(
                QOpenGLShader.Fragment, "uniform lowp float t;"
                "varying highp vec2 coords;"
                "void main() {"
                "    lowp float i = 1. - (pow(abs(coords.x), 4.) + pow(abs(coords.y), 4.));"
                "    i = smoothstep(t - 0.8, t + 0.8, i);"
                "    i = floor(i * 20.) / 20.;"
                "    gl_FragColor = vec4(coords * .5 + .5, i, i);"
                "}")

            self.m_program.bindAttributeLocation("vertices", 0)

            self.m_program.link()

        self.m_program.bind()

        self.m_program.enableAttributeArray(0)

        values = [(-1, -1), (1, -1), (-1, 1), (1, 1)]

        self.m_program.setAttributeArray(0, values)

        self.m_program.setUniformValue("t", self.m_t)

        #print("DATA:",self.m_viewportSize.width(), self.m_viewportSize.height(), self.m_t)#, self.gl.glViewport)

        self.gl.glViewport(0, 0, self.m_viewportSize.width(),
                           self.m_viewportSize.height())

        self.gl.glDisable(self.gl.GL_DEPTH_TEST)

        self.gl.glClearColor(0, 0, 0, 1)

        self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT)

        self.gl.glEnable(self.gl.GL_BLEND)

        self.gl.glBlendFunc(self.gl.GL_SRC_ALPHA, self.gl.GL_ONE)

        self.gl.glDrawArrays(self.gl.GL_TRIANGLE_STRIP, 0, 4)

        self.m_program.disableAttributeArray(0)

        self.m_program.release()
Exemple #15
0
class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, processor, df, parent=None):
        super().__init__(parent)
        self.parent = parent
        self.processor = processor
        # Data
        self.df = df

        # UI
        self.setupUi(self)
        self.setupControls()
        self.keyPressEvent = self.keyPressed
        self.mouseMoveEvent = self.mouseMoved

        # Control & Display
        self.mouse_grabbed = False

        self.camera_pos = QVector3D(0.5, 0.5, -2)  # Start camera position
        self.center = QVector3D(0.5, 0, 0.5)  # Center of object
        self.rot_center = QVector3D(0.5, 0.5, 0.5)  # Center of rotation
        self.camera_rot = QVector3D(0, 0, 1)  # Camera rotation
        self.scale_vec = QVector3D(1, 1, 1)  # Object scale
        self.real_prop = processor.get_real_scaling()  # val to lat

        self.light_pos = QVector3D(self.xLightSpinBox.value(),
                                   self.yLightSpinBox.value(),
                                   self.zLightSpinBox.value())
        self.ambient = self.ambientSlider.value() / 100
        self.diffuse = self.diffuseSlider.value() / 100
        self.alpha = self.alphaSlider.value() / 100  # Transparency

        # Drawing
        self.normals = []
        self.colors = []
        self.coords_array = []
        # !> len(self.normals) == len(self.colors) == len(self.coords_array)

        self.update_light = False  # Update for light is needed
        self.update_buffer = False  # Update for whole buffer is needed

        self.show_grid = self.gridCheckBox.isChecked()
        self.show_contour = self.contourCheckBox.isChecked()
        self.contour_levels = self.contourLevelSpinBox.value()
        self.show_light_lines = True
        self.grid_freq = 10

        self.grid_color = QVector4D(1, 1, 1, 1)
        self.contour_color = QVector4D(1, 1, 1, 1)
        self.light_line_color = QVector4D(1, 0.6, 0, 1)

        self.prepareScene()
        self.updateUi()

        self.shaders = QOpenGLShaderProgram()
        self.openGLWidget.initializeGL = self.initializeGL
        self.openGLWidget.paintGL = self.paintGL

    def updateUi(self):
        """Set up custom widgets & positions"""
        self.splitDockWidget(self.displayDockWidget, self.elevationDockWidget,
                             Qt.Vertical)
        self.splitDockWidget(self.elevationDockWidget, self.displayDockWidget,
                             Qt.Vertical)

        self.tabifyDockWidget(self.elevationDockWidget, self.minimapDockWidget)
        self.tabifyDockWidget(self.displayDockWidget, self.lightDockWidget)
        self.tabifyDockWidget(self.projDockWidget, self.additionalDockWidget)
        self.tabifyDockWidget(self.elevationDockWidget, self.cameraDockWidget)
        self.lightDockWidget.raise_()
        self.additionalDockWidget.raise_()
        self.elevationDockWidget.raise_()

        self.elevationWidget = ElevationGraphWidget(
            self.processor.min_val,
            self.processor.max_val,
            self.processor.denormalizeValue(self.camera_pos.y()),
            width=240,
            height=100)
        self.minimapWidget = MinimapGraphWidget(self.processor,
                                                self.camera_pos,
                                                self.camera_rot,
                                                width=240,
                                                height=100)
        self.elevationWidgetLayout.addWidget(self.elevationWidget)
        self.minimapLayout.addWidget(self.minimapWidget)
        self.mapDockWidgetControls()

        self.actionOpenAnother.triggered.connect(self.onOpenAnother)

    def onOpenAnother(self):
        """Open another GeoTIFF file"""
        self.parent.show()
        self.hide()
        self.deleteLater()

    def mapDockWidgetControls(self):
        """Show/hide dockwidgets via corresponding actions"""
        self.dock_widgets = [
            self.lightDockWidget, self.cameraDockWidget,
            self.additionalDockWidget, self.minimapDockWidget,
            self.displayDockWidget, self.projDockWidget,
            self.elevationDockWidget
        ]
        self.dock_actions = [
            self.actionShowLightSourceDW, self.actionShowCameraDW,
            self.actionShowAdditionalDW, self.actionShowMinimapDW,
            self.actionShowDisplayDW, self.actionShowProjectionDW,
            self.actionShowElevationDW
        ]
        for dock_widget, action in zip(self.dock_widgets, self.dock_actions):

            def wrapper(action):
                def dock_widget_close_event(event):
                    action.setChecked(False)
                    event.accept()

                return dock_widget_close_event

            dock_widget.closeEvent = wrapper(action)
            action.triggered.connect(dock_widget.setVisible)

    # ==================== PREPARATION ====================
    def prepareScene(self):
        """Prepare the data for bufferization"""
        self.coords_array = []
        self.colors = []
        self.normals = []
        polygons, normals, colors = self.getMapPolygons()
        self.map_data = self.preparePolygons(polygons, normals, colors)
        # self.normal_data = self.prepareNormalLines(polygons, normals, colors)

        polygons, normals, colors = self.getLightSourceCoords()
        self.light_data = self.preparePolygons(polygons, normals, colors)
        if self.show_light_lines:
            lines, line_colors = self.getLightLines()
            self.light_lines_data = self.prepareLines(lines, line_colors)

        if self.show_grid:
            lines, line_colors = self.getGrid()
            self.grid_data = self.prepareLines(lines, line_colors)
        if self.show_contour:
            self.contour_data = self.getContour()

    # POLYGONS
    def getLightSourceCoords(self):
        polygons = np.array([((0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0)),
                             ((0, 0, 1), (0, 1, 1), (1, 1, 1), (1, 0, 1)),
                             ((0, 0, 0), (0, 0, 1), (1, 0, 1), (1, 0, 0)),
                             ((0, 1, 0), (0, 1, 1), (1, 1, 1), (1, 1, 0)),
                             ((0, 0, 0), (0, 0, 1), (0, 1, 1), (0, 1, 0)),
                             ((1, 0, 0), (1, 0, 1), (1, 1, 1), (1, 1, 0))])
        normals = [(0, 0, -1), (0, 0, 1), (0, -1, 0), (0, 1, 0), (-1, 0, 0),
                   (1, 0, 0)]

        normals_vec = []
        [[
            normals_vec.append(QVector3D(*normals[i]))
            for _ in range(len(polygons[i]))
        ] for i in range(len(polygons))]

        center = np.array(
            (self.light_pos.x(), self.light_pos.y(), self.light_pos.z()))
        delta = np.array((0.5, 0.5, 0.5))
        polygons = [[(p - delta) * 0.05 + center for p in side]
                    for side in polygons]
        colors = []
        [
            colors.append(QVector4D(1, 153 / 255, 0, 1) * self.diffuse)
            for _ in range(len(normals_vec))
        ]
        return polygons, normals_vec, colors

    def getMapPolygons(self):
        polygons, normals, colors = [], [], []
        for polygon, normal in self.processor.polygon_generator(self.df):
            polygons.append(self.swapPoints(polygon))
            [
                normals.append(QVector3D(*self.swapPoint(*normal)))
                for _ in polygon
            ]
            [colors.append(self.getColorByValue(val)) for x, y, val in polygon]
        return polygons, normals, colors

    def getColorByValue(self, value):
        """Get QVector4D-color from green (value == 0) to red (value == 1)
        :param value: 0 - 1
        """
        hue = 120 * (1 - value) / 360
        color = QColor.fromHslF(hue, 1, 0.5)
        color_vec = QVector4D(color.redF(), color.greenF(), color.blueF(), 0.5)
        return color_vec

    def swapPoint(self, lon, lat, value):
        return lon, value, lat

    def swapPoints(self, polygon):
        return [(lon, value, lat) for lon, lat, value in polygon]

    def prepareNormalLines(self, polygons, normals, colors):
        """Normal lines for each polygon.
        Debug only
        """
        norm_i = 0
        start = len(self.coords_array)
        for polygon in polygons:
            point = polygon[0]
            normal = normals[norm_i]
            # color = colors[norm_i]
            color = QVector4D(1, 1, 1, 1)
            point_2 = QVector3D(*point) + normal * 0.04
            point_2 = (point_2.x(), point_2.y(), point_2.z())
            self.prepareLine((point, point_2), [color] * 2)
            norm_i += len(polygon)
        end = len(self.coords_array)
        return start, end

    def preparePolygons(self, polygons, normals, colors, start_index=None):
        """Prepare polygons for bufferization

        :param polygons: a list like [(p11, p12, ...), (p21, p22, ...)]
        :param normals: normals with number of normals equal to points
        :param colors: colors for each point
        :param start_index: if None, start at the end of each array.
        Otherwise, overwrite
        """
        assert len(normals) == len(colors)
        coords_array = []
        [[coords_array.append(list(p)) for p in polygon]
         for polygon in polygons]
        start = len(self.coords_array)
        if start_index is None:
            self.coords_array += coords_array
            self.normals += normals
            self.colors += colors
        else:
            for i, j in enumerate(
                    range(start_index, start_index + len(coords_array))):
                self.coords_array[j] = coords_array[i]
                self.normals[j] = normals[i]
                self.colors[j] = colors[i]
        end = len(self.coords_array)
        return start, end

    # LINES
    def getGrid(self):
        assert self.processor.min_lat != self.processor.max_lat \
            and self.processor.min_val != self.processor.max_val
        value = self.processor.min_val - \
            (self.processor.max_val - self.processor.min_val) * 0.1

        lines = []
        for lat in np.linspace(self.processor.min_lat, self.processor.max_lat,
                               self.grid_freq):
            line = ((self.processor.min_lon, lat, value),
                    (self.processor.max_lon, lat, value))
            lines.append(line)
        for lon in np.linspace(self.processor.min_lon, self.processor.max_lon,
                               self.grid_freq):
            line = ((lon, self.processor.min_lat, value),
                    (lon, self.processor.max_lat, value))
            lines.append(line)

        # lines.append(((self.min_lon, self.min_lat, self.min_val),
        #              (self.min_lon, self.min_lat, self.max_val)))

        lines = [
            self.swapPoints(self.processor.normalizePoints(line))
            for line in lines
        ]
        line_colors = [(self.grid_color, self.grid_color) for _ in lines]
        return lines, line_colors

    def getContour(self):
        lev_lines = self.processor.get_contour(levels=self.contour_levels)
        contour = []
        for level, line in lev_lines:
            line = [(self.processor.normalizeLon(lon),
                     self.processor.normalizeValue(level + 10),
                     self.processor.normalizeLat(lat)) for lon, lat in line]
            colors = [self.contour_color] * len(line)
            contour.append(self.prepareLine(line, colors))
        return contour

    def getLightLines(self):
        if self.processor.max_val == self.processor.min_val:
            v = 0
        else:
            v = self.processor.normalizeValue(
                self.processor.min_val -
                (self.processor.max_val - self.processor.min_val) * 0.1)
        lines = (((self.light_pos.x(), v, -100), (self.light_pos.x(), v, 100)),
                 ((-100, v, self.light_pos.z()), (100, v, self.light_pos.z())),
                 ((self.light_pos.x(), v, self.light_pos.z()),
                  (self.light_pos.x(), self.light_pos.y(),
                   self.light_pos.z())))
        line_colors = [(self.light_line_color, self.light_line_color)
                       for _ in lines]
        return lines, line_colors

    def prepareLines(self, lines, line_colors, start_index=None):
        """Prepare lines for bufferization

        :param lines: list like one for polygons
        :param line_colors: list of colors of each line
        :param start_index: start index
        """
        assert len(lines) == len(line_colors)
        if start_index is None:
            data = [None] * len(lines)
        else:
            data = []
            sum_len = 0
            for line in lines:
                data.append(start_index + sum_len)
                sum_len += len(line)

        result = [
            self.prepareLine(line, colors, datum)
            for line, colors, datum in zip(lines, line_colors, data)
        ]
        return result[0][0], result[-1][1]

    def prepareLine(self, line, colors, start_index=None):
        assert len(line) == len(colors)
        if start_index is None:
            start = len(self.coords_array)
            self.coords_array += line
            self.colors += colors
            self.normals += [QVector3D(0, 1, 0)] * len(line)
            end = len(self.coords_array)
        else:
            start = start_index
            for i, j in enumerate(range(start_index, start_index + len(line))):
                self.coords_array[j] = line[i]
                self.colors[j] = colors[i]
            end = start_index + len(line)
        return start, end

    # ==================== SCENE PREPARATION ====================
    def initializeGL(self):
        GL.glClearColor(0.1, 0.1, 0.1, 1.0)
        GL.glEnableClientState(GL.GL_VERTEX_ARRAY)
        self.setUpShaders()
        self.initVertexArrays()

    def setUpShaders(self):
        self.shaders.addShaderFromSourceFile(
            QOpenGLShader.Vertex, resource_path('shaders/shader.vert'))
        self.shaders.addShaderFromSourceFile(
            QOpenGLShader.Fragment, resource_path('shaders/shader.frag'))
        self.shaders.link()
        self.shaders.bind()

    def initVertexArrays(self):
        """Init buffers"""
        assert len(self.coords_array) == len(self.colors) == len(self.normals)
        GL.glVertexPointer(3, GL.GL_FLOAT, 0, self.coords_array)
        self.shaders.setAttributeArray("v_color", self.colors)
        self.shaders.enableAttributeArray("v_color")
        self.shaders.setAttributeArray("v_normal", self.normals)
        self.shaders.enableAttributeArray("v_normal")

    # ==================== UPDATING STUFF ====================
    def updateGL(func):
        def wrapper(self, *args, **kwargs):
            res = func(self, *args, **kwargs)
            self.openGLWidget.update()
            return res

        return wrapper

    def updateCameraInfo(func):
        """A decorator to update camera widgets after excution
        """
        def wrapper(self, *args, **kwargs):
            res = func(self, *args, **kwargs)
            coef = 1 if not self.realPropCheckBox.isChecked() \
                else self.real_prop
            self.elevationWidget.updatePos(
                self.processor.denormalizeValue(self.camera_pos.y() /
                                                (self.scale_vec.y()) * coef))
            self.minimapWidget.updateCameraInfo(
                self.camera_pos * self.scale_vec, self.camera_rot)
            return res

        return wrapper

    def updateLightData(self):
        """Update parts of buffer used to display the light source"""
        polygons, normals, colors = self.getLightSourceCoords()
        self.preparePolygons(polygons, normals, colors, self.light_data[0])
        lines, colors = self.getLightLines()
        self.prepareLines(lines, colors, self.light_lines_data[0])
        GL.glVertexPointer(3, GL.GL_FLOAT, 0, self.coords_array)
        self.update_light = False

    def updateBuffer(self):
        """Update the whole buffer"""
        self.prepareScene()
        self.initVertexArrays()
        self.update_buffer = False

    # ==================== ACTUAL DRAWING ====================
    def paintGL(self):
        self.loadScene()
        if self.update_light:
            self.updateLightData()
        if self.update_buffer:
            self.updateBuffer()
        self.updateMatrices()
        self.updateParams()
        self.drawScene()

    def loadScene(self):
        width, height = self.openGLWidget.width(), self.openGLWidget.height()
        view = max(width, height)
        GL.glViewport(int((width - view) / 2), int((height - view) / 2), view,
                      view)
        GL.glPolygonMode(GL.GL_FRONT_AND_BACK, GL.GL_FILL)
        GL.glEnable(GL.GL_BLEND)
        GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
        GL.glEnable(GL.GL_DEPTH_TEST)
        GL.glDepthFunc(GL.GL_LEQUAL)

    def updateMatrices(self):
        """Update projection matrices"""
        proj = QMatrix4x4()
        coef = 0.01
        center_x = 0
        center_y = 0
        projection = (-1 * coef + center_x, 1 * coef + center_x,
                      -1 * coef + center_y, 1 * coef + center_y, 2.8 * coef,
                      20)
        if self.perspectiveRadioButton.isChecked():
            proj.frustum(*projection)
        else:
            proj.ortho(*projection)
        modelview = QMatrix4x4()
        modelview.lookAt(self.camera_pos, self.camera_pos + self.camera_rot,
                         QVector3D(0, 1, 0))
        self.shaders.setUniformValue("ModelViewMatrix", modelview)
        self.shaders.setUniformValue("MVP", proj * modelview)

    def updateParams(self):
        """Update light, alpha and scaling parameters"""
        self.shaders.setUniformValue("LightPos", self.light_pos)
        self.shaders.setUniformValue("ambientStrength", self.ambient)
        self.shaders.setUniformValue("diffuseStrength", self.diffuse)
        self.shaders.setUniformValue("alpha", self.alpha)
        self.shaders.setUniformValue("center", self.center)
        self.shaders.setUniformValue("scale", self.scale_vec)

    def drawScene(self):
        """Paint all the prepared data"""
        GL.glClear(GL.GL_COLOR_BUFFER_BIT)
        self.shaders.setUniformValue('scaleEnabled', False)
        self.shaders.setUniformValue('phongModel', False)
        self.drawPreparedPolygons(*self.light_data)
        if self.show_light_lines:
            self.drawPreparedLines(*self.light_lines_data)

        self.shaders.setUniformValue('scaleEnabled', True)
        if self.show_grid:
            self.drawPreparedLines(*self.grid_data)

        # self.drawPreparedLines(*self.normal_data)
        self.shaders.setUniformValue('phongModel', True)
        self.drawPreparedPolygons(*self.map_data)

        if self.show_contour:
            self.shaders.setUniformValue('phongModel', False)
            self.drawPreparedLineStrips(self.contour_data)

    def drawPreparedPolygons(self, start, end):
        for i in range(start, end, 4):
            GL.glDrawArrays(GL.GL_POLYGON, i, 4)

    def drawPreparedLines(self, start, end):
        GL.glDrawArrays(GL.GL_LINES, start, end - start)

    def drawPreparedLineStrips(self, arr):
        for start, end in arr:
            GL.glDrawArrays(GL.GL_LINE_STRIP, start, end - start)

    # ==================== CONTROLS ====================
    def setupControls(self):
        """Connect controls to this class' methods"""
        # Camera
        self.moveCameraUp.clicked.connect(lambda: self.moveCamera(az=1))
        self.moveCameraDown.clicked.connect(lambda: self.moveCamera(az=-1))
        self.moveCameraLeft.clicked.connect(lambda: self.moveCamera(pol=1))
        self.moveCameraRight.clicked.connect(lambda: self.moveCamera(pol=-1))
        self.moveCameraForward.clicked.connect(lambda: self.moveCamera(z=-1))
        self.moveCameraBackward.clicked.connect(lambda: self.moveCamera(z=1))

        # Scaling
        self.xScaleSpinBox.valueChanged.connect(lambda x: self.scaleView(x=x))
        self.yScaleSpinBox.valueChanged.connect(lambda y: self.scaleView(y=y))
        self.zScaleSpinBox.valueChanged.connect(lambda z: self.scaleView(z=z))
        self.realPropCheckBox.stateChanged.connect(
            lambda: self.scaleView(y=self.yScaleSpinBox.value()))

        # Light
        self.ambientSlider.valueChanged.connect(
            lambda ambient: self.setLight(ambient=ambient / 100))
        self.diffuseSlider.valueChanged.connect(
            lambda diffuse: self.setLight(diffuse=diffuse / 100))

        self.xLightSpinBox.valueChanged.connect(lambda x: self.setLight(x=x))
        self.yLightSpinBox.valueChanged.connect(lambda y: self.setLight(y=y))
        self.zLightSpinBox.valueChanged.connect(lambda z: self.setLight(z=z))

        # Display
        self.gridCheckBox.toggled.connect(lambda g: self.setGrid(show=g))
        self.contourCheckBox.toggled.connect(lambda c: self.setContour(show=c))
        self.contourLevelSpinBox.valueChanged.connect(
            lambda l: self.setContour(levels=l))

        # Misc
        self.alphaSlider.valueChanged.connect(
            lambda alpha: self.setDisplay(alpha / 100))
        self.actionGrabKeyboard.toggled.connect(self.toggleGrabKeyboard)
        self.actionGrabMouse.toggled.connect(self.toggleGrabMouse)
        self.orhogonalRadioButton.clicked.connect(self.openGLWidget.update)
        self.perspectiveRadioButton.clicked.connect(self.openGLWidget.update)

        self.openGLWidget.mousePressEvent \
            = lambda event: self.actionGrabMouse.setChecked(True)

    def keyPressed(self, event):
        key = event.key()
        camera_dict = {
            Qt.Key_W: {
                'z': 1
            },
            Qt.Key_S: {
                'z': -1
            },
            Qt.Key_A: {
                'x': -1
            },
            Qt.Key_D: {
                'x': 1
            },
            Qt.Key_Z: {
                'y': 1
            },
            Qt.Key_X: {
                'y': -1
            },
            Qt.Key_Up: {
                'az': 1
            },
            Qt.Key_Down: {
                'az': -1
            },
            Qt.Key_Left: {
                'pol': 1
            },
            Qt.Key_Right: {
                'pol': -1
            }
        }
        self.moveCamera(**camera_dict.get(key, {}))
        if key == Qt.Key_Escape:
            self.actionGrabMouse.setChecked(False)
            self.actionGrabKeyboard.setChecked(False)

    def mouseMoved(self, event):
        az_sensivity = 0.03
        pol_sensivity = 0.03
        if self.mouse_grabbed:
            delta = event.globalPos() - self.mouse_center
            QCursor.setPos(self.mouse_center)
            if event.buttons() == Qt.RightButton:
                self.moveCameraAroundCenter(az=delta.y() * az_sensivity,
                                            pol=delta.x() * pol_sensivity)
            else:
                self.moveCamera(az=delta.y() * az_sensivity,
                                pol=delta.x() * pol_sensivity)
        else:
            super().mouseMoveEvent(event)

    def getRotVec(self):
        rot_matr = QMatrix4x4()
        rot_matr.rotate(-90, 0, 1, 0)
        rot_vec = QVector3D(self.camera_rot)
        rot_vec.setY(0)
        rot_vec = rot_matr * rot_vec
        return rot_vec

    @updateGL
    @updateCameraInfo
    def moveCamera(self, az=0, pol=0, x=0, y=0, z=0):
        move_coef = 0.1
        rot_coef = 2

        rot_vec = self.getRotVec()

        if az != 0 or pol != 0:
            rot_matr = QMatrix4x4()
            rot_matr.rotate(rot_coef * az, rot_vec)
            rot_matr.rotate(rot_coef * pol, 0, 1, 0)
            self.camera_rot = rot_matr * self.camera_rot
        if z:
            self.camera_pos += move_coef * self.camera_rot * z
        if x:
            self.camera_pos += rot_vec * move_coef * x
        if y:
            self.camera_pos.setY(self.camera_pos.y() + y * move_coef)

    @updateGL
    @updateCameraInfo
    def moveCameraAroundCenter(self, az=0, pol=0):
        rot_coef = 4

        rot_vec = self.getRotVec()
        rot_matr = QMatrix4x4()
        rot_matr.rotate(rot_coef * az, rot_vec)
        rot_matr.rotate(rot_coef * pol, 0, 1, 0)
        rot_center = self.rot_center * self.scale_vec

        self.camera_pos -= rot_center
        self.camera_pos = rot_matr * self.camera_pos
        self.camera_pos += rot_center

        self.camera_rot = -self.camera_pos + rot_center

    @updateGL
    @updateCameraInfo
    def scaleView(self, x=None, y=None, z=None):
        if x:
            self.scale_vec.setX(x)
        if y:
            if self.realPropCheckBox.isChecked():
                self.scale_vec.setY(y * self.real_prop)
            else:
                self.scale_vec.setY(y)
        if z:
            self.scale_vec.setZ(z)

    @updateGL
    def setLight(self, x=None, y=None, z=None, ambient=None, diffuse=None):
        if x:
            self.light_pos.setX(x)
        if y:
            self.light_pos.setY(y)
        if z:
            self.light_pos.setZ(z)
        if ambient:
            self.ambient = ambient
        if diffuse:
            self.diffuse = diffuse
        self.update_light = True

    @updateGL
    def setDisplay(self, alpha=None, invisible=None):
        if invisible:
            self.invisible = invisible
        if alpha:
            self.alpha = alpha

    @updateGL
    def setGrid(self, show):
        self.show_grid = show
        self.update_buffer = True

    @updateGL
    def setContour(self, show=None, levels=None):
        if show is not None:
            self.show_contour = show
            self.update_buffer = True
        if levels is not None:
            self.contour_levels = levels
            if self.show_contour:
                self.update_buffer = True

    def toggleGrabKeyboard(self, grab: bool):
        if grab:
            self.grabKeyboard()
        else:
            self.releaseKeyboard()

    def toggleGrabMouse(self, grab: bool):
        self.actionGrabKeyboard.setChecked(grab)
        self.mouse_grabbed = grab
        if grab:
            self.setCursor(Qt.BlankCursor)
            self.mouse_center = self.getMouseCenter()
            QCursor.setPos(self.mouse_center)
            self.setMouseTracking(True)
            self.grabMouse()
        else:
            self.setCursor(Qt.ArrowCursor)
            self.setMouseTracking(False)
            self.releaseMouse()

    def getMouseCenter(self):
        w, h = self.openGLWidget.width(), self.openGLWidget.height()
        local_center = QPoint(w / 2, h / 2)
        global_center = self.mapToGlobal(self.openGLWidget.pos()) \
            + local_center
        return global_center
Exemple #16
0
class SquircleRenderer(QObject):  # QOpenGLFunctions
    """docstring for SquircleRenderer"""

    def __init__(self, parent=None):
        super(SquircleRenderer, self).__init__(parent)
        self.m_t = 0.0
        self.m_program = None
        self.m_viewportSize = QSize()

    def setT(self, t):
        self.m_t = t

    def setViewportSize(self, size):
        self.m_viewportSize = size

    def setWin(self, win):
        self.win = win

        ver = QOpenGLVersionProfile()
        ver.setVersion(2, 1)

        self.m_context = self.win.openglContext()
        self.gl = self.m_context.versionFunctions(ver)

    @pyqtSlot()
    def paint(self):
        if not self.m_program:
            self.gl.initializeOpenGLFunctions()

            self.m_program = QOpenGLShaderProgram(self)
            self.m_program.addShaderFromSourceCode(
                QOpenGLShader.Vertex,
                "attribute highp vec4 vertices;"
                "varying highp vec2 coords;"
                "void main() {"
                "    gl_Position = vertices;"
                "    coords = vertices.xy;"
                "}",
            )
            self.m_program.addShaderFromSourceCode(
                QOpenGLShader.Fragment,
                "uniform lowp float t;"
                "varying highp vec2 coords;"
                "void main() {"
                "    lowp float i = 1. - (pow(abs(coords.x), 4.) + pow(abs(coords.y), 4.));"
                "    i = smoothstep(t - 0.8, t + 0.8, i);"
                "    i = floor(i * 20.) / 20.;"
                "    gl_FragColor = vec4(coords * .5 + .5, i, i);"
                "}",
            )

            self.m_program.bindAttributeLocation("vertices", 0)

            self.m_program.link()

        self.m_program.bind()

        self.m_program.enableAttributeArray(0)

        values = [(-1, -1), (1, -1), (-1, 1), (1, 1)]

        self.m_program.setAttributeArray(0, values)

        self.m_program.setUniformValue("t", self.m_t)

        # print("DATA:",self.m_viewportSize.width(), self.m_viewportSize.height(), self.m_t)#, self.gl.glViewport)

        self.gl.glViewport(0, 0, self.m_viewportSize.width(), self.m_viewportSize.height())

        self.gl.glDisable(self.gl.GL_DEPTH_TEST)

        self.gl.glClearColor(0, 0, 0, 1)

        self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT)

        self.gl.glEnable(self.gl.GL_BLEND)

        self.gl.glBlendFunc(self.gl.GL_SRC_ALPHA, self.gl.GL_ONE)

        self.gl.glDrawArrays(self.gl.GL_TRIANGLE_STRIP, 0, 4)

        self.m_program.disableAttributeArray(0)

        self.m_program.release()
Exemple #17
0
class LogoRenderer():#protected QOpenGLFunctions
    """docstring for LogoRenderer"""
    def __init__(self):
        super(LogoRenderer, self).__init__()
        self.m_fAngle = None
        self.m_fScale = None
        self.vertices = []
        self.normals = []
        self.program1 = QOpenGLShaderProgram()
        self.vertexAttr1 = 0
        self.normalAttr1 = 0
        self.matrixUniform1 = 0

        ver = QOpenGLVersionProfile()
        ver.setVersion(2, 1)
        cntx = QOpenGLContext.currentContext()
        #print("QOpenGLContext:", cntx, ver)
        fmt = cntx.format()
        fmt.setVersion(2, 1)
        cntx.setFormat(fmt)
        self.gl = cntx.versionFunctions(ver)


    def render(self):
        self.gl.glDepthMask(True)

        self.gl.glClearColor(0.5, 0.5, 0.7, 1.0)
        self.gl.glClear(self.gl.GL_COLOR_BUFFER_BIT | self.gl.GL_DEPTH_BUFFER_BIT)

        self.gl.glTexParameteri(self.gl.GL_TEXTURE_2D, self.gl.GL_TEXTURE_MIN_FILTER, self.gl.GL_LINEAR )
        self.gl.glTexParameteri(self.gl.GL_TEXTURE_2D, self.gl.GL_TEXTURE_MAG_FILTER, self.gl.GL_LINEAR )

        self.gl.glFrontFace(self.gl.GL_CW)
        self.gl.glCullFace(self.gl.GL_FRONT)
        self.gl.glEnable(self.gl.GL_CULL_FACE)
        self.gl.glEnable(self.gl.GL_DEPTH_TEST)

        modelview = QMatrix4x4()
        modelview.rotate(self.m_fAngle, 0.0, 1.0, 0.0)
        modelview.rotate(self.m_fAngle, 1.0, 0.0, 0.0)
        modelview.rotate(self.m_fAngle, 0.0, 0.0, 1.0)
        modelview.scale(self.m_fScale)
        modelview.translate(0.0, -0.2, 0.0)

        self.program1.bind()
        self.program1.setUniformValue(self.matrixUniform1, modelview)
        self.paintQtLogo()
        self.program1.release()

        self.gl.glDisable(self.gl.GL_DEPTH_TEST)
        self.gl.glDisable(self.gl.GL_CULL_FACE)

        self.m_fAngle += 1.0

    def initialize(self):
        #print("initialize.gls")
        self.gl.initializeOpenGLFunctions()

        self.gl.glClearColor(0.1, 0.1, 0.2, 1.0)

        vshader1 = QOpenGLShader(QOpenGLShader.Vertex, self.program1)
        vsrc1 = str("attribute highp vec4 vertex;\n"
                "attribute mediump vec3 normal;\n"
                "uniform mediump mat4 matrix;\n"
                "varying mediump vec4 color;\n"
                "void main(void)\n"
                "{\n"
                "    vec3 toLight = normalize(vec3(0.0, 0.3, 1.0));\n"
                "    float angle = max(dot(normal, toLight), 0.0);\n"
                "    vec3 col = vec3(0.40, 1.0, 0.0);\n"
                "    color = vec4(col * 0.2 + col * 0.8 * angle, 1.0);\n"
                "    color = clamp(color, 0.0, 1.0);\n"
                "    gl_Position = matrix * vertex;\n"
                "}\n")
        vshader1.compileSourceCode(vsrc1)

        fshader1 = QOpenGLShader(QOpenGLShader.Fragment, self.program1)
        fsrc1 = str("varying mediump vec4 color;\n"
                "void main(void)\n"
                "{\n"
                "    gl_FragColor = color;\n"
                "}\n")
        fshader1.compileSourceCode(fsrc1)

        self.program1.addShader(vshader1)
        self.program1.addShader(fshader1)
        self.program1.link()

        self.vertexAttr1 = self.program1.attributeLocation("vertex")
        self.normalAttr1 = self.program1.attributeLocation("normal")
        self.matrixUniform1 = self.program1.uniformLocation("matrix")

        self.gl.glTexParameteri(self.gl.GL_TEXTURE_2D, self.gl.GL_TEXTURE_MIN_FILTER, self.gl.GL_LINEAR )
        self.gl.glTexParameteri(self.gl.GL_TEXTURE_2D, self.gl.GL_TEXTURE_MAG_FILTER, self.gl.GL_LINEAR )

        self.m_fAngle = 0
        self.m_fScale = 1
        self.createGeometry()

    def paintQtLogo(self):
        self.program1.enableAttributeArray(self.normalAttr1)
        self.program1.enableAttributeArray(self.vertexAttr1)
        self.program1.setAttributeArray(self.vertexAttr1, self.vertices)
        self.program1.setAttributeArray(self.normalAttr1, self.normals)
        self.gl.glDrawArrays(self.gl.GL_TRIANGLES, 0, len(self.vertices))
        self.program1.disableAttributeArray(self.normalAttr1)
        self.program1.disableAttributeArray(self.vertexAttr1)

    def createGeometry(self):
        self.vertices.clear()
        self.normals.clear()

        x1 = +0.06
        y1 = -0.14
        x2 = +0.14
        y2 = -0.06
        x3 = +0.08
        y3 = +0.00
        x4 = +0.30
        y4 = +0.22

        self.quad(x1, y1, x2, y2, y2, x2, y1, x1)
        self.quad(x3, y3, x4, y4, y4, x4, y3, x3)

        self.extrude(x1, y1, x2, y2)
        self.extrude(x2, y2, y2, x2)
        self.extrude(y2, x2, y1, x1)
        self.extrude(y1, x1, x1, y1)
        self.extrude(x3, y3, x4, y4)
        self.extrude(x4, y4, y4, x4)
        self.extrude(y4, x4, y3, x3)

        NumSectors = 100

        for i in range(NumSectors):
            angle1 = (i * 2 * math.pi) / NumSectors
            x5 = 0.30 * math.sin(angle1)
            y5 = 0.30 * math.cos(angle1)
            x6 = 0.20 * math.sin(angle1)
            y6 = 0.20 * math.cos(angle1)

            angle2 = ((i + 1) * 2 * math.pi) / NumSectors
            x7 = 0.20 * math.sin(angle2)
            y7 = 0.20 * math.cos(angle2)
            x8 = 0.30 * math.sin(angle2)
            y8 = 0.30 * math.cos(angle2)

            self.quad(x5, y5, x6, y6, x7, y7, x8, y8)

            self.extrude(x6, y6, x7, y7)
            self.extrude(x8, y8, x5, y5)
        

        for i in range(len(self.vertices)):
            self.vertices[i] *= 2.0



    def quad(self, x1, y1, x2, y2, x3, y3, x4, y4):
        #print("quad inicio")
        self.vertices.append(QVector3D(x1, y1, -0.05))
        self.vertices.append(QVector3D(x2, y2, -0.05))
        self.vertices.append(QVector3D(x4, y4, -0.05))

        self.vertices.append(QVector3D(x3, y3, -0.05))
        self.vertices.append(QVector3D(x4, y4, -0.05))
        self.vertices.append(QVector3D(x2, y2, -0.05))

        n = QVector3D.normal(QVector3D(x2 - x1, y2 - y1, 0.0), QVector3D(x4 - x1, y4 - y1, 0.0))

        for i in range(6):
            self.normals.append(n)

        self.vertices.append(QVector3D(x4, y4, 0.05))
        self.vertices.append(QVector3D(x2, y2, 0.05))
        self.vertices.append(QVector3D(x1, y1, 0.05))

        self.vertices.append(QVector3D(x2, y2, 0.05))
        self.vertices.append(QVector3D(x4, y4, 0.05))
        self.vertices.append(QVector3D(x3, y3, 0.05))

        n = QVector3D.normal(QVector3D(x2 - x4, y2 - y4, 0.0), QVector3D(x1 - x4, y1 - y4, 0.0))

        for i in range(6):
            self.normals.append(n)
        #print("quad fin")

    def extrude(self, x1, y1, x2, y2):
        #print("extrude inicio")
        self.vertices.append(QVector3D(x1, y1, +0.05))
        self.vertices.append(QVector3D(x2, y2, +0.05))
        self.vertices.append(QVector3D(x1, y1, -0.05))

        self.vertices.append(QVector3D(x2, y2, -0.05))
        self.vertices.append(QVector3D(x1, y1, -0.05))
        self.vertices.append(QVector3D(x2, y2, +0.05))

        n = QVector3D.normal(QVector3D(x2 - x1, y2 - y1, 0.0), QVector3D(0.0, 0.0, -0.1))

        for i in range(6):
            self.normals.append(n)