1 2############################################################################ 3## 4## Copyright (C) 2013 Riverbank Computing Limited. 5## Copyright (C) 2016 The Qt Company Ltd. 6## Contact: http://www.qt.io/licensing/ 7## 8## This file is part of the Qt for Python examples of the Qt Toolkit. 9## 10## $QT_BEGIN_LICENSE:BSD$ 11## You may use this file under the terms of the BSD license as follows: 12## 13## "Redistribution and use in source and binary forms, with or without 14## modification, are permitted provided that the following conditions are 15## met: 16## * Redistributions of source code must retain the above copyright 17## notice, this list of conditions and the following disclaimer. 18## * Redistributions in binary form must reproduce the above copyright 19## notice, this list of conditions and the following disclaimer in 20## the documentation and/or other materials provided with the 21## distribution. 22## * Neither the name of The Qt Company Ltd nor the names of its 23## contributors may be used to endorse or promote products derived 24## from this software without specific prior written permission. 25## 26## 27## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 30## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 31## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 32## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 33## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 34## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 35## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 37## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 38## 39## $QT_END_LICENSE$ 40## 41############################################################################ 42 43"""PySide2 port of the opengl/legacy/hellogl example from Qt v5.x""" 44 45import sys 46import math 47from PySide2 import QtCore, QtGui, QtWidgets, QtOpenGL 48 49try: 50 from OpenGL import GL 51except ImportError: 52 app = QtWidgets.QApplication(sys.argv) 53 messageBox = QtWidgets.QMessageBox(QtWidgets.QMessageBox.Critical, "OpenGL hellogl", 54 "PyOpenGL must be installed to run this example.", 55 QtWidgets.QMessageBox.Close) 56 messageBox.setDetailedText("Run:\npip install PyOpenGL PyOpenGL_accelerate") 57 messageBox.exec_() 58 sys.exit(1) 59 60 61class Window(QtWidgets.QWidget): 62 def __init__(self, parent=None): 63 QtWidgets.QWidget.__init__(self, parent) 64 65 self.glWidget = GLWidget() 66 67 self.xSlider = self.createSlider(QtCore.SIGNAL("xRotationChanged(int)"), 68 self.glWidget.setXRotation) 69 self.ySlider = self.createSlider(QtCore.SIGNAL("yRotationChanged(int)"), 70 self.glWidget.setYRotation) 71 self.zSlider = self.createSlider(QtCore.SIGNAL("zRotationChanged(int)"), 72 self.glWidget.setZRotation) 73 74 mainLayout = QtWidgets.QHBoxLayout() 75 mainLayout.addWidget(self.glWidget) 76 mainLayout.addWidget(self.xSlider) 77 mainLayout.addWidget(self.ySlider) 78 mainLayout.addWidget(self.zSlider) 79 self.setLayout(mainLayout) 80 81 self.xSlider.setValue(170 * 16) 82 self.ySlider.setValue(160 * 16) 83 self.zSlider.setValue(90 * 16) 84 85 self.setWindowTitle(self.tr("Hello GL")) 86 87 def createSlider(self, changedSignal, setterSlot): 88 slider = QtWidgets.QSlider(QtCore.Qt.Vertical) 89 90 slider.setRange(0, 360 * 16) 91 slider.setSingleStep(16) 92 slider.setPageStep(15 * 16) 93 slider.setTickInterval(15 * 16) 94 slider.setTickPosition(QtWidgets.QSlider.TicksRight) 95 96 self.glWidget.connect(slider, QtCore.SIGNAL("valueChanged(int)"), setterSlot) 97 self.connect(self.glWidget, changedSignal, slider, QtCore.SLOT("setValue(int)")) 98 99 return slider 100 101 102class GLWidget(QtOpenGL.QGLWidget): 103 xRotationChanged = QtCore.Signal(int) 104 yRotationChanged = QtCore.Signal(int) 105 zRotationChanged = QtCore.Signal(int) 106 107 def __init__(self, parent=None): 108 QtOpenGL.QGLWidget.__init__(self, parent) 109 110 self.object = 0 111 self.xRot = 0 112 self.yRot = 0 113 self.zRot = 0 114 115 self.lastPos = QtCore.QPoint() 116 117 self.trolltechGreen = QtGui.QColor.fromCmykF(0.40, 0.0, 1.0, 0.0) 118 self.trolltechPurple = QtGui.QColor.fromCmykF(0.39, 0.39, 0.0, 0.0) 119 120 def xRotation(self): 121 return self.xRot 122 123 def yRotation(self): 124 return self.yRot 125 126 def zRotation(self): 127 return self.zRot 128 129 def minimumSizeHint(self): 130 return QtCore.QSize(50, 50) 131 132 def sizeHint(self): 133 return QtCore.QSize(400, 400) 134 135 def setXRotation(self, angle): 136 angle = self.normalizeAngle(angle) 137 if angle != self.xRot: 138 self.xRot = angle 139 self.emit(QtCore.SIGNAL("xRotationChanged(int)"), angle) 140 self.updateGL() 141 142 def setYRotation(self, angle): 143 angle = self.normalizeAngle(angle) 144 if angle != self.yRot: 145 self.yRot = angle 146 self.emit(QtCore.SIGNAL("yRotationChanged(int)"), angle) 147 self.updateGL() 148 149 def setZRotation(self, angle): 150 angle = self.normalizeAngle(angle) 151 if angle != self.zRot: 152 self.zRot = angle 153 self.emit(QtCore.SIGNAL("zRotationChanged(int)"), angle) 154 self.updateGL() 155 156 def initializeGL(self): 157 self.qglClearColor(self.trolltechPurple.darker()) 158 self.object = self.makeObject() 159 GL.glShadeModel(GL.GL_FLAT) 160 GL.glEnable(GL.GL_DEPTH_TEST) 161 GL.glEnable(GL.GL_CULL_FACE) 162 163 def paintGL(self): 164 GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) 165 GL.glLoadIdentity() 166 GL.glTranslated(0.0, 0.0, -10.0) 167 GL.glRotated(self.xRot / 16.0, 1.0, 0.0, 0.0) 168 GL.glRotated(self.yRot / 16.0, 0.0, 1.0, 0.0) 169 GL.glRotated(self.zRot / 16.0, 0.0, 0.0, 1.0) 170 GL.glCallList(self.object) 171 172 def resizeGL(self, width, height): 173 side = min(width, height) 174 GL.glViewport(int((width - side) / 2),int((height - side) / 2), side, side) 175 176 GL.glMatrixMode(GL.GL_PROJECTION) 177 GL.glLoadIdentity() 178 GL.glOrtho(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0) 179 GL.glMatrixMode(GL.GL_MODELVIEW) 180 181 def mousePressEvent(self, event): 182 self.lastPos = QtCore.QPoint(event.pos()) 183 184 def mouseMoveEvent(self, event): 185 dx = event.x() - self.lastPos.x() 186 dy = event.y() - self.lastPos.y() 187 188 if event.buttons() & QtCore.Qt.LeftButton: 189 self.setXRotation(self.xRot + 8 * dy) 190 self.setYRotation(self.yRot + 8 * dx) 191 elif event.buttons() & QtCore.Qt.RightButton: 192 self.setXRotation(self.xRot + 8 * dy) 193 self.setZRotation(self.zRot + 8 * dx) 194 195 self.lastPos = QtCore.QPoint(event.pos()) 196 197 def makeObject(self): 198 genList = GL.glGenLists(1) 199 GL.glNewList(genList, GL.GL_COMPILE) 200 201 GL.glBegin(GL.GL_QUADS) 202 203 x1 = +0.06 204 y1 = -0.14 205 x2 = +0.14 206 y2 = -0.06 207 x3 = +0.08 208 y3 = +0.00 209 x4 = +0.30 210 y4 = +0.22 211 212 self.quad(x1, y1, x2, y2, y2, x2, y1, x1) 213 self.quad(x3, y3, x4, y4, y4, x4, y3, x3) 214 215 self.extrude(x1, y1, x2, y2) 216 self.extrude(x2, y2, y2, x2) 217 self.extrude(y2, x2, y1, x1) 218 self.extrude(y1, x1, x1, y1) 219 self.extrude(x3, y3, x4, y4) 220 self.extrude(x4, y4, y4, x4) 221 self.extrude(y4, x4, y3, x3) 222 223 Pi = 3.14159265358979323846 224 NumSectors = 200 225 226 for i in range(NumSectors): 227 angle1 = (i * 2 * Pi) / NumSectors 228 x5 = 0.30 * math.sin(angle1) 229 y5 = 0.30 * math.cos(angle1) 230 x6 = 0.20 * math.sin(angle1) 231 y6 = 0.20 * math.cos(angle1) 232 233 angle2 = ((i + 1) * 2 * Pi) / NumSectors 234 x7 = 0.20 * math.sin(angle2) 235 y7 = 0.20 * math.cos(angle2) 236 x8 = 0.30 * math.sin(angle2) 237 y8 = 0.30 * math.cos(angle2) 238 239 self.quad(x5, y5, x6, y6, x7, y7, x8, y8) 240 241 self.extrude(x6, y6, x7, y7) 242 self.extrude(x8, y8, x5, y5) 243 244 GL.glEnd() 245 GL.glEndList() 246 247 return genList 248 249 def quad(self, x1, y1, x2, y2, x3, y3, x4, y4): 250 self.qglColor(self.trolltechGreen) 251 252 GL.glVertex3d(x1, y1, +0.05) 253 GL.glVertex3d(x2, y2, +0.05) 254 GL.glVertex3d(x3, y3, +0.05) 255 GL.glVertex3d(x4, y4, +0.05) 256 257 GL.glVertex3d(x4, y4, -0.05) 258 GL.glVertex3d(x3, y3, -0.05) 259 GL.glVertex3d(x2, y2, -0.05) 260 GL.glVertex3d(x1, y1, -0.05) 261 262 def extrude(self, x1, y1, x2, y2): 263 self.qglColor(self.trolltechGreen.darker(250 + int(100 * x1))) 264 265 GL.glVertex3d(x1, y1, -0.05) 266 GL.glVertex3d(x2, y2, -0.05) 267 GL.glVertex3d(x2, y2, +0.05) 268 GL.glVertex3d(x1, y1, +0.05) 269 270 def normalizeAngle(self, angle): 271 while angle < 0: 272 angle += 360 * 16 273 while angle > 360 * 16: 274 angle -= 360 * 16 275 return angle 276 277 def freeResources(self): 278 self.makeCurrent() 279 GL.glDeleteLists(self.object, 1) 280 281if __name__ == '__main__': 282 app = QtWidgets.QApplication(sys.argv) 283 window = Window() 284 window.show() 285 res = app.exec_() 286 window.glWidget.freeResources() 287 sys.exit(res) 288