|
| 1 | +#!/usr/bin/env python |
| 2 | +from __future__ import print_function |
| 3 | +from PyQt5.QtGui import QOpenGLWindow,QSurfaceFormat |
| 4 | +from PyQt5.QtWidgets import QApplication |
| 5 | +from PyQt5.QtCore import * |
| 6 | +import sys |
| 7 | +from pyngl import * |
| 8 | +from OpenGL.GL import * |
| 9 | + |
| 10 | +class MainWindow(QOpenGLWindow) : |
| 11 | + |
| 12 | + def __init__(self, parent=None): |
| 13 | + super(QOpenGLWindow, self).__init__(parent) |
| 14 | + self.mouseGlobalTX=Mat4() |
| 15 | + self.width=int(1024) |
| 16 | + self.height=int(720) |
| 17 | + self.setTitle('Boid') |
| 18 | + self.spinXFace = int(0) |
| 19 | + self.spinYFace = int(0) |
| 20 | + self.rotate = False |
| 21 | + self.translate = False |
| 22 | + self.origX = int(0) |
| 23 | + self.origY = int(0) |
| 24 | + self.origXPos = int(0) |
| 25 | + self.origYPos = int(0) |
| 26 | + self.INCREMENT=0.01 |
| 27 | + self.ZOOM=0.1 |
| 28 | + self.modelPos=Vec3() |
| 29 | + self.view=Mat4() |
| 30 | + self.project=Mat4() |
| 31 | + self.vao=None |
| 32 | + |
| 33 | + def initializeGL(self) : |
| 34 | + self.makeCurrent() |
| 35 | + NGLInit.instance() |
| 36 | + glClearColor( 0.4, 0.4, 0.4, 1.0 ) |
| 37 | + glEnable( GL_DEPTH_TEST ) |
| 38 | + glEnable( GL_MULTISAMPLE ) |
| 39 | + shader=ShaderLib.instance() |
| 40 | + shader.loadShader('Phong','shaders/PhongVertex.glsl','shaders/PhongFragment.glsl',ErrorExit.OFF) |
| 41 | + shader.use('Phong') |
| 42 | + lightPos=Vec4(-2.0,5.0,2.0,0.0) |
| 43 | + shader.setUniform('light.position',lightPos) |
| 44 | + shader.setUniform('light.ambient',0.0,0.0,0.0,1.0) |
| 45 | + shader.setUniform('light.diffuse',1.0,1.0,1.0,1.0); |
| 46 | + shader.setUniform('light.specular',0.8,0.8,0.8,1.0); |
| 47 | + shader.setUniform('material.ambient',0.274725,0.1995,0.0745,0.0); |
| 48 | + shader.setUniform('material.diffuse',0.75164,0.60648,0.22648,0.0); |
| 49 | + shader.setUniform('material.specular',0.628281,0.555802,0.3666065,0.0); |
| 50 | + shader.setUniform('material.shininess',51.2); |
| 51 | + shader.setUniform('viewerPos',0,1,5); |
| 52 | + |
| 53 | + |
| 54 | + self.view=lookAt(Vec3(0,1,5),Vec3.zero(),Vec3.up()) |
| 55 | + self.project=perspective( 45.0, float(self.width)/float(self.height), 0.05, 350.0 ) |
| 56 | + self.buildVAO() |
| 57 | + |
| 58 | + |
| 59 | + def buildVAO(self) : |
| 60 | + verts=VectorVec3([ |
| 61 | + Vec3(0.0,1.0,1.0), |
| 62 | + Vec3(0.0,0.0,-1.0), |
| 63 | + Vec3(-0.5,0.0,1.0), |
| 64 | + Vec3(0.0,1.0,1.0), |
| 65 | + Vec3(0.0,0.0,-1.0), |
| 66 | + Vec3(0.5,0.0,1.0), |
| 67 | + Vec3(0.0,1.0,1.0), |
| 68 | + Vec3(0.0,0.0,1.5), |
| 69 | + Vec3(-0.5,0.0,1.0), |
| 70 | + Vec3(0.0,1.0,1.0), |
| 71 | + Vec3(0.0,0.0,1.5), |
| 72 | + Vec3(0.5,0.0,1.0)]) |
| 73 | + |
| 74 | + normals=VectorVec3() |
| 75 | + n=calcNormal(verts[2],verts[1],verts[0]); |
| 76 | + normals.extend([n,n,n]) |
| 77 | + n=calcNormal(verts[3],verts[4],verts[5]); |
| 78 | + normals.extend([n,n,n]) |
| 79 | + n=calcNormal(verts[6],verts[7],verts[8]); |
| 80 | + normals.extend([n,n,n]) |
| 81 | + n=calcNormal(verts[11],verts[10],verts[9]); |
| 82 | + normals.extend([n,n,n]) |
| 83 | + |
| 84 | + self.vao=VAOFactory.createVAO(multiBufferVAO,GL_TRIANGLES) |
| 85 | + self.vao.bind() |
| 86 | + self.vao.setData(len(verts)*Vec3.sizeof(),verts) |
| 87 | + self.vao.setVertexAttributePointer(0,3,GL_FLOAT,0,0) |
| 88 | + self.vao.setData(len(normals)*Vec3.sizeof(),normals) |
| 89 | + self.vao.setVertexAttributePointer(1,3,GL_FLOAT,0,0) |
| 90 | + self.vao.setNumIndices(len(verts)) |
| 91 | + self.vao.unbind() |
| 92 | + |
| 93 | + |
| 94 | + def loadMatricesToShader(self) : |
| 95 | + shader = ShaderLib.instance() |
| 96 | + shader.use('Phong') |
| 97 | + |
| 98 | + MV= self.view*self.mouseGlobalTX |
| 99 | + MVP= self.project*MV; |
| 100 | + normalMatrix=Mat3(MV) |
| 101 | + normalMatrix.inverse().transpose() |
| 102 | + shader.setUniform("MV",MV) |
| 103 | + shader.setUniform("MVP",MVP) |
| 104 | + shader.setUniform("normalMatrix",normalMatrix) |
| 105 | + shader.setUniform("M",self.mouseGlobalTX) |
| 106 | + |
| 107 | + def paintGL(self): |
| 108 | + try : |
| 109 | + self.makeCurrent() |
| 110 | + glViewport( 0, 0, self.width, self.height ) |
| 111 | + glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) |
| 112 | + shader=ShaderLib.instance() |
| 113 | + rotX=Mat4() |
| 114 | + rotY=Mat4() |
| 115 | + rotX.rotateX( self.spinXFace ) |
| 116 | + rotY.rotateY( self.spinYFace ) |
| 117 | + self.mouseGlobalTX = rotY * rotX |
| 118 | + self.mouseGlobalTX.m_30 = self.modelPos.m_x |
| 119 | + self.mouseGlobalTX.m_31 = self.modelPos.m_y |
| 120 | + self.mouseGlobalTX.m_32 = self.modelPos.m_z |
| 121 | + self.loadMatricesToShader() |
| 122 | + self.vao.bind() |
| 123 | + self.vao.draw() |
| 124 | + self.vao.unbind() |
| 125 | + except OpenGL.error.GLError : |
| 126 | + print ('error') |
| 127 | + |
| 128 | + def resizeGL(self, w,h) : |
| 129 | + self.width=int(w* self.devicePixelRatio()) |
| 130 | + self.height=int(h* self.devicePixelRatio()) |
| 131 | + self.project=perspective( 45.0, float( w ) / h, 0.05, 350.0 ) |
| 132 | + |
| 133 | + |
| 134 | + |
| 135 | + def keyPressEvent(self, event) : |
| 136 | + key=event.key() |
| 137 | + if key==Qt.Key_Escape : |
| 138 | + exit() |
| 139 | + elif key==Qt.Key_W : |
| 140 | + glPolygonMode(GL_FRONT_AND_BACK,GL_LINE) |
| 141 | + elif key==Qt.Key_S : |
| 142 | + glPolygonMode(GL_FRONT_AND_BACK,GL_FILL) |
| 143 | + elif key==Qt.Key_Space : |
| 144 | + self.spinXFace=0 |
| 145 | + self.spinYFace=0 |
| 146 | + self.modelPos.set(Vec3.zero()) |
| 147 | + |
| 148 | + self.update() |
| 149 | + |
| 150 | + def mouseMoveEvent(self, event) : |
| 151 | + if self.rotate and event.buttons() == Qt.LeftButton : |
| 152 | + diffx = event.x() - self.origX |
| 153 | + diffy = event.y() - self.origY |
| 154 | + self.spinXFace += int( 0.5 * diffy ) |
| 155 | + self.spinYFace += int( 0.5 * diffx ) |
| 156 | + self.origX = event.x() |
| 157 | + self.origY = event.y() |
| 158 | + self.update() |
| 159 | + |
| 160 | + elif self.translate and event.buttons() == Qt.RightButton : |
| 161 | + |
| 162 | + diffX = int( event.x() - self.origXPos ) |
| 163 | + diffY = int( event.y() - self.origYPos ) |
| 164 | + self.origXPos = event.x() |
| 165 | + self.origYPos = event.y() |
| 166 | + self.modelPos.m_x += self.INCREMENT * diffX |
| 167 | + self.modelPos.m_y -= self.INCREMENT * diffY |
| 168 | + self.update() |
| 169 | + |
| 170 | + def mousePressEvent(self,event) : |
| 171 | + if event.button() == Qt.LeftButton : |
| 172 | + self.origX = event.x() |
| 173 | + self.origY = event.y() |
| 174 | + self.rotate = True |
| 175 | + |
| 176 | + elif event.button() == Qt.RightButton : |
| 177 | + self.origXPos = event.x() |
| 178 | + self.origYPos = event.y() |
| 179 | + self.translate = True |
| 180 | + |
| 181 | + def mouseReleaseEvent(self,event) : |
| 182 | + if event.button() == Qt.LeftButton : |
| 183 | + self.rotate = False |
| 184 | + |
| 185 | + elif event.button() == Qt.RightButton : |
| 186 | + self.translate = False |
| 187 | + |
| 188 | + def wheelEvent(self,event) : |
| 189 | + numPixels = event.pixelDelta() |
| 190 | + |
| 191 | + if numPixels.x() > 0 : |
| 192 | + self.modelPos.m_z += self.ZOOM |
| 193 | + |
| 194 | + elif numPixels.x() < 0 : |
| 195 | + self.modelPos.m_z -= self.ZOOM |
| 196 | + self.update() |
| 197 | + |
| 198 | + |
| 199 | +if __name__ == '__main__': |
| 200 | + app = QApplication(sys.argv) |
| 201 | + format=QSurfaceFormat() |
| 202 | + format.setSamples(4) |
| 203 | + format.setMajorVersion(4) |
| 204 | + format.setMinorVersion(1) |
| 205 | + format.setProfile(QSurfaceFormat.CoreProfile) |
| 206 | + # now set the depth buffer to 24 bits |
| 207 | + format.setDepthBufferSize(24) |
| 208 | + # set that as the default format for all windows |
| 209 | + QSurfaceFormat.setDefaultFormat(format) |
| 210 | + |
| 211 | + window = MainWindow() |
| 212 | + window.setFormat(format) |
| 213 | + window.resize(1024,720) |
| 214 | + window.show() |
| 215 | + sys.exit(app.exec_()) |
0 commit comments