def __init__(self, geometries, board, parent): format = QGLFormat() format.setSampleBuffers(True) format.setSamples(8) super(GLWidget, self).__init__(format, parent) self.camera = Camera() self.light = Light() self.mouse = Mouse() self.geometries = geometries self.board = board
class GLWidget(QGLWidget): def __init__(self, geometries, board, parent): format = QGLFormat() format.setSampleBuffers(True) format.setSamples(8) super(GLWidget, self).__init__(format, parent) self.camera = Camera() self.light = Light() self.mouse = Mouse() self.geometries = geometries self.board = board def initializeGL(self): # init window and context glClearColor(0.5, 0.5, 1.0, 1.0) # load VBOs self.VBOs = defaultdict(lambda: []) for name, geo in self.geometries.items(): for i in range(len(geo.vertices)): vertices = geo.vertices[i] normals = geo.normals[i] tangents = geo.tangents[i] bitangents = geo.bitangents[i] self.VBOs[name].append(vbo.VBO(np.concatenate((vertices, normals, tangents, bitangents), axis=1))) glEnable(GL_CULL_FACE) glCullFace(GL_FRONT) self.fbo_factory = FBOFactory() self.fbo_factory.resize(self.width(), self.height()) self.object_fbo = self.fbo_factory.create() self.gaussian1_fbo = self.fbo_factory.create(depth_buffer=False) self.gaussian2_fbo = self.fbo_factory.create() self.brightparts_fbo = self.fbo_factory.create() self.edgedetection_fbo = self.fbo_factory.create() self.main_program = MainProgram() self.chessboard_program = ChessboardProgram() self.texture_program = TextureProgram() self.edge_program = EdgeDetectionProgram() self.brightparts_program = BrightpartsProgram() self.twotextures_program = TwoTexturesProgram() self.gaussianblur1 = GaussianBlurPass1Program() self.gaussianblur2 = GaussianBlurPass2Program() self.animations = [] QTimer.singleShot(0, self.update) def paintGL(self): now = time() # draw chessman to get contour with self.object_fbo: glEnable(GL_DEPTH_TEST) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.main_program.set_view_matrix(self._view_matrix()) self.main_program.set_light(self.light) self.main_program.set_camera(self.camera) for name, position in self._scene_objects(): self._draw_object(name, position) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self._draw_board() for name, position in self._scene_objects(): self._draw_object(name, position) glDisable(GL_DEPTH_TEST) # glow on bright parts with self.brightparts_fbo: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.brightparts_program.set_threshold(0.9) self.brightparts_program.set_fbo(self.object_fbo) self.brightparts_program.draw() with self.gaussian1_fbo: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.gaussianblur1.set_fbo(self.brightparts_fbo) self.gaussianblur1.draw() with self.gaussian2_fbo: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.gaussianblur2.set_fbo(self.gaussian1_fbo) self.gaussianblur2.draw() glEnable(GL_BLEND) glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA) self.texture_program.set_fbo(self.gaussian2_fbo) self.texture_program.draw() glDisable(GL_BLEND) with self.edgedetection_fbo: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.edge_program.set_threshold(2) self.edge_program.set_fbo(self.object_fbo) self.edge_program.set_view_matrix(self._view_matrix()) for name, position in self._scene_objects(): self._draw_edge(name, position) with self.gaussian1_fbo: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.gaussianblur1.set_fbo(self.edgedetection_fbo) self.gaussianblur1.draw() with self.gaussian2_fbo: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) self.gaussianblur2.set_fbo(self.gaussian1_fbo) self.gaussianblur2.draw() glEnable(GL_BLEND) glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_DST_COLOR) self.texture_program.set_fbo(self.gaussian2_fbo) self.texture_program.draw() glDisable(GL_BLEND) fps = 1/(time() - now) # print(fps) def resizeGL(self, width, height): # projection matrix glViewport(0, 0, self.width(), self.height()) self.main_program.set_projection_matrix(self._projection_matrix()) self.chessboard_program.set_projection_matrix(self._projection_matrix()) self.texture_program.resize(width, height) self.edge_program.resize(self._projection_matrix(), width, height) self.brightparts_program.resize(width, height) self.fbo_factory.resize(width, height) self.gaussianblur1.resize(width, height) self.gaussianblur2.resize(width, height) def mousePressEvent(self, event): self.mouse.x = event.pos().x() self.mouse.y = event.pos().y() z = glReadPixels(self.mouse.x, self.mouse.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT)[0][0] self._detect_collision(self.mouse.x, self.mouse.y, z) def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: self.camera.go_right(event.pos().x() - self.mouse.x) self.camera.go_up(event.pos().y() - self.mouse.y) self.updateGL() self.mouse.x = event.pos().x() self.mouse.y = event.pos().y() def wheelEvent(self, event): self.camera.go_forward(event.delta()/5000) def update(self): try: for i in range(len(self.animations)): anim = self.animations[i] if anim.update(): del self.animations[i] self.updateGL() finally: QTimer.singleShot(0, self.update) def _detect_collision(self, x, y, z): # normalize x = (2 * x) / self.width() - 1 y = 1 - (2 * y) / self.height() z = 2 * z - 1 position = np.array([x, y, z, 1], dtype=np.float64) # print(position) position = position.dot(np.linalg.inv(self._projection_matrix())) print(position) # position = position.dot(np.linalg.inv(self._view_matrix())) position /= position[3] print(position) print() def _projection_matrix(self): return perspective(45, self.width()/self.height(), 0.1, 100) # return ortho(-30, 30, -30, 30, 0, 100) def _view_matrix(self): return look_at(self.camera.position, self.camera.direction, (0,1,0)) def _model_matrix(self, geo, position): return reduce(np.dot, [scale(geo.scaling), rotate(geo.rotation[0], [1, 0, 0]), rotate(geo.rotation[1], [0, 1, 0]), rotate(geo.rotation[2], [0, 0, 1]), translate(geo.translation), translate([(position[0])*4, 0, (position[1])*4])]) def _scene_objects(self): for cell in self.board: if isinstance(cell, King): if cell.color == Color.WHITE: name = 'WhiteKing' else: name = 'BlackKing' elif isinstance(cell, Queen): if cell.color == Color.WHITE: name = 'WhiteQueen' else: name = 'BlackQueen' elif isinstance(cell, Bishop): if cell.color == Color.WHITE: name = 'WhiteBishop' else: name = 'BlackBishop' elif isinstance(cell, Knight): if cell.color == Color.WHITE: name = 'WhiteKnight' else: name = 'BlackKnight' elif isinstance(cell, Rook): if cell.color == Color.WHITE: name = 'WhiteRook' else: name = 'BlackRook' elif isinstance(cell, Pawn): if cell.color == Color.WHITE: name = 'WhitePawn' else: name = 'BlackPawn' yield name, cell.position def _draw_board(self): self.chessboard_program.set_view_matrix(self._view_matrix()) self.chessboard_program.set_light(self.light) self.chessboard_program.set_camera(self.camera) vbos = self.VBOs['Chessboard'] geo = self.geometries['Chessboard'] for i in range(len(vbos)): vbo = vbos[i] effect = geo.materials[i] model = self._model_matrix(geo, [0, 0]) self.chessboard_program.draw(vbo, model, effect) def _draw_object(self, name, position): vbos = self.VBOs[name] geo = self.geometries[name] for i in range(len(vbos)): vbo = vbos[i] effect = geo.materials[i] model = self._model_matrix(geo, position) self.main_program.draw(vbo, model, effect) def _draw_edge(self, name, position): vbos = self.VBOs[name] geo = self.geometries[name] for vbo in vbos: model = self._model_matrix(geo, position) self.edge_program.draw(vbo, model)