def make_current(self): """ Makes _context current for the surface of this window Returns ------- bool True if successful False if an error occurs """ success = False if self._context is None: self._context = QOpenGLContext() self._context.create() success = self._context.makeCurrent(self) if success: # self.initializeOpenGLFunctions() self._context.doneCurrent() else: return success if self._context is not None: success = self._context.makeCurrent(self) # err = glGetError() return success
def renderNow(self): if not self.isExposed(): return self.m_update_pending = False needsInitialize = False if self.m_context is None: self.m_context = QOpenGLContext(self) self.surface_format = QSurfaceFormat() self.surface_format.setVersion(4, 1) self.surface_format.setProfile(QSurfaceFormat.CoreProfile) self.m_context.setFormat(self.surface_format) self.m_context.create() needsInitialize = True self.m_context.makeCurrent(self) if needsInitialize: self.initialize() self.render() self.m_context.swapBuffers(self) if self.m_animating: self.renderLater()
def renderNow(self): if not self.isExposed(): return self.m_update_pending = False needsInitialize = False if self.m_context is None: self.m_context = QOpenGLContext(self) self.m_context.setFormat(self.requestedFormat()) self.m_context.create() needsInitialize = True self.m_context.makeCurrent(self) if needsInitialize: version_profile = QOpenGLVersionProfile() version_profile.setVersion(2, 0) self.m_gl = self.m_context.versionFunctions(version_profile) self.m_gl.initializeOpenGLFunctions() self.initialize() self.render(self.m_gl) self.m_context.swapBuffers(self) if self.m_animating: self.renderLater()
def setContext(cls, major_version: int, minor_version: int, core=False, profile=None): new_format = QSurfaceFormat() new_format.setMajorVersion(major_version) new_format.setMinorVersion(minor_version) if core: profile_ = QSurfaceFormat.CoreProfile else: profile_ = QSurfaceFormat.CompatibilityProfile if profile is not None: profile_ = profile new_format.setProfile(profile_) new_context = QOpenGLContext() new_context.setFormat(new_format) success = new_context.create() if success: return new_context else: Logger.log( "e", "Failed creating OpenGL context (%d, %d, core=%s)" % (major_version, minor_version, core)) return None
def setContext(cls, major_version: int, minor_version: int, core=False, profile=None): """Set OpenGL context, given major, minor version + core using QOpenGLContext Unfortunately, what you get back does not have to be the requested version. """ new_format = QSurfaceFormat() new_format.setMajorVersion(major_version) new_format.setMinorVersion(minor_version) if core: profile_ = QSurfaceFormat.CoreProfile else: profile_ = QSurfaceFormat.CompatibilityProfile if profile is not None: profile_ = profile new_format.setProfile(profile_) new_context = QOpenGLContext() new_context.setFormat(new_format) success = new_context.create() if success: return new_context else: Logger.log( "e", "Failed creating OpenGL context (%d, %d, core=%s)" % (major_version, minor_version, core)) return None
def renderNow(self): if not self.isExposed(): return self.m_update_pending = False needsInitialise = False if self.m_context is None: self.m_context = QOpenGLContext(self) self.m_context.setFormat(self.requestedFormat()) self.m_context.create() needsInitialise = True self.m_context.makeCurrent(self) if needsInitialise: self.initialise() self.render() self.m_context.swapBuffers(self) if self.m_animating: self.renderLater()
def initializeGL(self): qDebug("initializeGL()") if self.logger: self.logger.initialize() self.logger.messageLogged.connect(lambda message: qDebug(self.__tr("OpenGL debug message: {0}").fomat(message.message()))) self.logger.startLogging() gl = QOpenGLContext.currentContext().versionFunctions(glVersionProfile) QOpenGLContext.currentContext().aboutToBeDestroyed.connect(self.cleanup) self.clean = False fragmentShader = None vertexShader = vertexShader2D if self.ddsFile.isCubemap: fragmentShader = fragmentShaderCube vertexShader = vertexShaderCube if QOpenGLContext.currentContext().hasExtension(b"GL_ARB_seamless_cube_map"): GL_TEXTURE_CUBE_MAP_SEAMLESS = 0x884F gl.glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS) elif self.ddsFile.glFormat.samplerType == "F": fragmentShader = fragmentShaderFloat elif self.ddsFile.glFormat.samplerType == "UI": fragmentShader = fragmentShaderUInt else: fragmentShader = fragmentShaderSInt self.program = QOpenGLShaderProgram(self) self.program.addShaderFromSourceCode(QOpenGLShader.Vertex, vertexShader) self.program.addShaderFromSourceCode(QOpenGLShader.Fragment, fragmentShader) self.program.bindAttributeLocation("position", 0) self.program.bindAttributeLocation("texCoordIn", 1) self.program.link() self.transparecyProgram = QOpenGLShaderProgram(self) self.transparecyProgram.addShaderFromSourceCode(QOpenGLShader.Vertex, transparencyVS) self.transparecyProgram.addShaderFromSourceCode(QOpenGLShader.Fragment, transparencyFS) self.transparecyProgram.bindAttributeLocation("position", 0) self.transparecyProgram.link() self.vao = QOpenGLVertexArrayObject(self) vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao) self.vbo = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer) self.vbo.create() self.vbo.bind() theBytes = struct.pack("%sf" % len(vertices), *vertices) self.vbo.allocate(theBytes, len(theBytes)) gl.glEnableVertexAttribArray(0) gl.glEnableVertexAttribArray(1) gl.glVertexAttribPointer(0, 4, gl.GL_FLOAT, False, 6 * 4, 0) gl.glVertexAttribPointer(1, 2, gl.GL_FLOAT, False, 6 * 4, 4 * 4) self.texture = self.ddsFile.asQOpenGLTexture(gl, QOpenGLContext.currentContext())
def started_(self): self.ctx = QOpenGLContext(self.offscreen_surface) self.ctx.setFormat(self.offscreen_surface.requestedFormat()) self.ctx.create() self.fbo = -1 self.tex = -1 self.rbuf = -1 self.setup_fbo() self.renderer = ModelRenderer(self.workspace, self.offscreen_surface)
def __init__(self, parent=None, **kwargs): super(ViewerWindow, self).__init__(parent) self.setSurfaceType(QWindow.OpenGLSurface) format = QSurfaceFormat() format.setVersion(3, 3) format.setProfile(QSurfaceFormat.CoreProfile) format.setStereo(False) format.setSwapBehavior(QSurfaceFormat.DoubleBuffer) format.setDepthBufferSize(24) format.setSamples(16) self.context = QOpenGLContext(self) self.context.setFormat(format) if not self.context.create(): raise Exception('self.context.create() failed') self.create() size = 720, 720 self.resize(*size) self.context.makeCurrent(self) self.hud_program = CrossHairProgram() self.default_view = np.eye(4, dtype=np.float32) self.view = self.default_view self.model = np.eye(4, dtype=np.float32) self.projection = np.eye(4, dtype=np.float32) self.layer_manager = LayerManager() self.visibility_toggle_listeners = [] self.multiview = True self.rotation = q.quaternion() self.scale = 0.6 self.translation = np.zeros(3) self.radius = 0.5 * min(*size) self.fov = 5. self.camera_position = -12. self.near_clip = .1 if 'near_clip' in kwargs: self.near_clip = kwargs['near_clip'] self.far_clip = 100. if 'far_clip' in kwargs: self.far_clip = kwargs['far_clip'] self.projection_mode = 'perspective' # 'orthographic' self.size = size self.bg_white = False self.viewpoint_dict = {} print((self.instructions))
def opengl_info() -> Optional[OpenGLInfo]: # pragma: no cover """Get the OpenGL vendor used. This returns a string such as 'nouveau' or 'Intel Open Source Technology Center'; or None if the vendor can't be determined. """ assert QApplication.instance() override = os.environ.get('QUTE_FAKE_OPENGL') if override is not None: log.init.debug("Using override {}".format(override)) vendor, version = override.split(', ', maxsplit=1) return OpenGLInfo.parse(vendor=vendor, version=version) old_context = cast(Optional[QOpenGLContext], QOpenGLContext.currentContext()) old_surface = None if old_context is None else old_context.surface() surface = QOffscreenSurface() surface.create() ctx = QOpenGLContext() ok = ctx.create() if not ok: log.init.debug("Creating context failed!") return None ok = ctx.makeCurrent(surface) if not ok: log.init.debug("Making context current failed!") return None try: if ctx.isOpenGLES(): # Can't use versionFunctions there return OpenGLInfo(gles=True) vp = QOpenGLVersionProfile() vp.setVersion(2, 0) try: vf = ctx.versionFunctions(vp) except ImportError as e: log.init.debug("Importing version functions failed: {}".format(e)) return None if vf is None: log.init.debug("Getting version functions failed!") return None vendor = vf.glGetString(vf.GL_VENDOR) version = vf.glGetString(vf.GL_VERSION) return OpenGLInfo.parse(vendor=vendor, version=version) finally: ctx.doneCurrent() if old_context and old_surface: old_context.makeCurrent(old_surface)
def offscreen_context(format): """Provide a temporary QOpenGLContext with the given QSurfaceFormat on an QOffscreenSurface.""" surface = QOffscreenSurface() surface.create() context = QOpenGLContext() context.setFormat(format) context.create() context.makeCurrent(surface) try: yield context finally: context.doneCurrent()
def __init__(self, args, glWidget=QOpenGLWidget, requestedGLVersion=(2, 1)): super(_TestApplication, self).__init__(args) glType = QOpenGLContext.openGLModuleType() format = QSurfaceFormat() format.setDepthBufferSize(24) if glType == QOpenGLContext.LibGL: info("OPENGL MODULE TYPE", "LibGL") format.setVersion(requestedGLVersion[0], requestedGLVersion[1]) format.setProfile(QSurfaceFormat.CompatibilityProfile) format.setOption(QSurfaceFormat.DebugContext) QSurfaceFormat.setDefaultFormat(format) else: info( "OPENGL MODULE TYPE", "Unknown or LibGLES <--- this is likely to cause problems down the line" ) self.debugMembers = False self.mainWin = QWidget() if glWidget == QOpenGLWidget: # Only hard code size if we're not using a canvas self.mainWin.resize(600, 600) self.mainWin.setWindowTitle('TestApplication') self.mainWidget = glWidget() self.layout = QHBoxLayout(self.mainWin) self.layout.addWidget(self.mainWidget) self.mainWin.show() ctx = QOpenGLContext.currentContext() info("GL CURRENT CONTEXT", ctx) format = ctx.format() info("EFFECTIVE GL VERSION", ctx.format().version()) self.aboutToQuit.connect(self.applicationClosing)
def __init__(self) -> None: if OpenGL.__instance is not None: raise RuntimeError("Try to create singleton '%s' more than once" % self.__class__.__name__) OpenGL.__instance = self super().__init__() profile = QOpenGLVersionProfile() profile.setVersion(OpenGLContext.major_version, OpenGLContext.minor_version) profile.setProfile(OpenGLContext.profile) self._gl = QOpenGLContext.currentContext().versionFunctions(profile) # type: Any #It's actually a protected class in PyQt that depends on the implementation of your graphics card. if not self._gl: Logger.log("e", "Startup failed due to OpenGL initialization failing") QMessageBox.critical(None, i18n_catalog.i18nc("@message", "Failed to Initialize OpenGL", "Could not initialize OpenGL. This program requires OpenGL 2.0 or higher. Please check your video card drivers.")) sys.exit(1) # It would be nice to be able to not necessarily need OpenGL FrameBuffer Object support, but # due to a limitation in PyQt, currently glReadPixels or similar methods are not available. # This means we can only get frame buffer contents through methods that indirectly call # those methods, in this case primarily QOpenGLFrameBufferObject::toImage(), making us # hard-depend on FrameBuffer Objects. if not self.hasFrameBufferObjects(): Logger.log("e", "Startup failed, OpenGL does not support Frame Buffer Objects") QMessageBox.critical(None, i18n_catalog.i18nc("Critical OpenGL Extensions Missing", "Critical OpenGL extensions are missing. This program requires support for Framebuffer Objects. Please check your video card drivers.")) sys.exit(1) self._gl.initializeOpenGLFunctions() self._gpu_vendor = OpenGL.Vendor.Other #type: int vendor_string = self._gl.glGetString(self._gl.GL_VENDOR) if vendor_string is None: vendor_string = "Unknown" vendor_string = vendor_string.lower() if "nvidia" in vendor_string: self._gpu_vendor = OpenGL.Vendor.NVidia elif "amd" in vendor_string or "ati" in vendor_string: self._gpu_vendor = OpenGL.Vendor.AMD elif "intel" in vendor_string: self._gpu_vendor = OpenGL.Vendor.Intel # WORKAROUND: Cura/#1117 Cura-packaging/12 # Some Intel GPU chipsets return a string, which is not undecodable via PyQt5. # This workaround makes the code fall back to a "Unknown" renderer in these cases. try: self._gpu_type = self._gl.glGetString(self._gl.GL_RENDERER) #type: str except UnicodeDecodeError: Logger.log("e", "DecodeError while getting GL_RENDERER via glGetString!") self._gpu_type = "Unknown" #type: str self._opengl_version = self._gl.glGetString(self._gl.GL_VERSION) #type: str if not self.hasFrameBufferObjects(): Logger.log("w", "No frame buffer support, falling back to texture copies.") Logger.log("d", "Initialized OpenGL subsystems.") Logger.log("d", "OpenGL Version: %s", self._opengl_version) Logger.log("d", "OpenGL Vendor: %s", self._gl.glGetString(self._gl.GL_VENDOR)) Logger.log("d", "OpenGL Renderer: %s", self._gpu_type)
def initializeGL(self): import seamless from PyQt5.QtGui import QOpenGLContext if self._destroyed: return try: old_running_qt = seamless._running_qt seamless._running_qt = True activate_opengl() ctx = self.context() assert ctx is QOpenGLContext.currentContext() #print("start initializeGL") if not self._initialized: add_opengl_context(ctx) self._initialized = True self.camera.width = self.width() self.camera.height = self.height() self.camera._write() #print("INIT") PINS.init.set() #print("end initializeGL") finally: seamless._running_qt = old_running_qt deactivate_opengl() super().initializeGL() seamless.run_work()
def _initialize(self): profile = QOpenGLVersionProfile() profile.setVersion(2, 0) self._gl = QOpenGLContext.currentContext().versionFunctions(profile) self._gl.initializeOpenGLFunctions() self._default_material = self.createMaterial( Resources.getPath(Resources.Shaders, "default.vert"), Resources.getPath(Resources.Shaders, "default.frag")) self._default_material.setUniformValue("u_ambientColor", Color(0.3, 0.3, 0.3, 1.0)) self._default_material.setUniformValue("u_diffuseColor", Color(0.5, 0.5, 0.5, 1.0)) self._default_material.setUniformValue("u_specularColor", Color(0.7, 0.7, 0.7, 1.0)) self._default_material.setUniformValue("u_shininess", 20.) self._selection_buffer = self.createFrameBuffer(128, 128) self._selection_material = self.createMaterial( Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "color.frag")) self._handle_material = self.createMaterial( Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "vertexcolor.frag")) self._outline_material = self.createMaterial( Resources.getPath(Resources.Shaders, "outline.vert"), Resources.getPath(Resources.Shaders, "outline.frag")) self._initialized = True
def event(self, event): if event.type == Event.ViewActivateEvent: # FIX: on Max OS X, somehow QOpenGLContext.currentContext() can become None during View switching. # This can happen when you do the following steps: # 1. Start Cura # 2. Load a model # 3. Switch to Custom mode # 4. Select the model and click on the per-object tool icon # 5. Switch view to Layer view or X-Ray # 6. Cura will very likely crash # It seems to be a timing issue that the currentContext can somehow be empty, but I have no clue why. # This fix tries to reschedule the view changing event call on the Qt thread again if the current OpenGL # context is None. if Platform.isOSX(): if QOpenGLContext.currentContext() is None: Logger.log("d", "current context of OpenGL is empty on Mac OS X, will try to create shaders later") Application.getInstance().callLater(lambda e = event: self.event(e)) return if event.type == Event.ViewDeactivateEvent: if self._composite_pass and 'xray' in self._composite_pass.getLayerBindings(): self.getRenderer().removeRenderPass(self._xray_pass) self._composite_pass.setLayerBindings(self._old_layer_bindings) self._composite_pass.setCompositeShader(self._old_composite_shader) self._xray_warning_message.hide()
def renderNow(self): if not self.isExposed(): return self.m_update_pending = False needsInitialize = False if self.m_context is None: self.m_context = QOpenGLContext(self) self.m_context.setFormat(self.requestedFormat()) self.m_context.create() needsInitialize = True self.m_context.makeCurrent(self) if needsInitialize: self.m_gl = self.m_context.versionFunctions() self.m_gl.initializeOpenGLFunctions() self.initialize() self.render(self.m_gl) self.m_context.swapBuffers(self) if self.m_animating: self.renderLater()
def create(self): from PyQt5.QtGui import QOpenGLContext self._id = gl.glGenTextures(1) context = QOpenGLContext.currentContext() self._opengl_context = context from seamless import add_opengl_destructor add_opengl_destructor(context, self.destroy)
def paintGL(self): qDebug("paintGL()") gl = QOpenGLContext.currentContext().versionFunctions(glVersionProfile) vaoBinder = QOpenGLVertexArrayObject.Binder(self.vao) # Draw checkerboard so transparency is obvious self.transparecyProgram.bind() if self.backgroundColour and self.backgroundColour.isValid(): self.transparecyProgram.setUniformValue("backgroundColour", self.backgroundColour) gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) self.transparecyProgram.release() self.program.bind() if self.texture: self.texture.bind() gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) gl.glDrawArrays(gl.GL_TRIANGLES, 0, 6) if self.texture: self.texture.release() self.program.release()
def _initialize(self): profile = QOpenGLVersionProfile() profile.setVersion(2, 0) self._gl = QOpenGLContext.currentContext().versionFunctions(profile) self._gl.initializeOpenGLFunctions() self._default_material = self.createMaterial( Resources.getPath(Resources.Shaders, "default.vert"), Resources.getPath(Resources.Shaders, "default.frag") ) self._default_material.setUniformValue("u_ambientColor", Color(0.3, 0.3, 0.3, 1.0)) self._default_material.setUniformValue("u_diffuseColor", Color(0.5, 0.5, 0.5, 1.0)) self._default_material.setUniformValue("u_specularColor", Color(0.7, 0.7, 0.7, 1.0)) self._default_material.setUniformValue("u_shininess", 20.) self._selection_buffer = self.createFrameBuffer(128, 128) self._selection_material = self.createMaterial( Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "color.frag") ) self._handle_material = self.createMaterial( Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "vertexcolor.frag") ) self._outline_material = self.createMaterial( Resources.getPath(Resources.Shaders, "outline.vert"), Resources.getPath(Resources.Shaders, "outline.frag") ) self._initialized = True
def event(self, event): if event.type == Event.ViewActivateEvent: # FIX: on Max OS X, somehow QOpenGLContext.currentContext() can become None during View switching. # This can happen when you do the following steps: # 1. Start Cura # 2. Load a model # 3. Switch to Custom mode # 4. Select the model and click on the per-object tool icon # 5. Switch view to Layer view or X-Ray # 6. Cura will very likely crash # It seems to be a timing issue that the currentContext can somehow be empty, but I have no clue why. # This fix tries to reschedule the view changing event call on the Qt thread again if the current OpenGL # context is None. if Platform.isOSX(): if QOpenGLContext.currentContext() is None: Logger.log( "d", "current context of OpenGL is empty on Mac OS X, will try to create shaders later" ) CuraApplication.getInstance().callLater( lambda e=event: self.event(e)) return if not self._xray_pass: # Currently the RenderPass constructor requires a size > 0 # This should be fixed in RenderPass's constructor. self._xray_pass = XRayPass.XRayPass(1, 1) self.getRenderer().addRenderPass(self._xray_pass) if not self._xray_composite_shader: self._xray_composite_shader = OpenGL.getInstance( ).createShaderProgram( Resources.getPath(Resources.Shaders, "xray_composite.shader")) theme = Application.getInstance().getTheme() self._xray_composite_shader.setUniformValue( "u_background_color", Color(*theme.getColor("viewport_background").getRgb())) self._xray_composite_shader.setUniformValue( "u_outline_color", Color(*theme.getColor("model_selection_outline").getRgb())) if not self._composite_pass: self._composite_pass = self.getRenderer().getRenderPass( "composite") self._old_layer_bindings = self._composite_pass.getLayerBindings() self._composite_pass.setLayerBindings( ["default", "selection", "xray"]) self._old_composite_shader = self._composite_pass.getCompositeShader( ) self._composite_pass.setCompositeShader( self._xray_composite_shader) if event.type == Event.ViewDeactivateEvent: self.getRenderer().removeRenderPass(self._xray_pass) self._composite_pass.setLayerBindings(self._old_layer_bindings) self._composite_pass.setCompositeShader(self._old_composite_shader)
def setupUI(self): self.setSurfaceType(QWindow.OpenGLSurface) self.renderctxt = QOpenGLContext(self) self.renderctxt.setFormat(self.requestedFormat()) self.renderctxt.create() self.renderctxt.makeCurrent(self) self.glfunc = self.renderctxt.versionFunctions() self.glfunc.initializeOpenGLFunctions()
def isOpenGLES(): try: # isOpenGLES() was introduced in Qt v5.3. return QOpenGLContext.currentContext().isOpenGLES() except: pass return False
def __init__(self): profile = QOpenGLVersionProfile() profile.setVersion(OpenGLContext.major_version, OpenGLContext.minor_version) profile.setProfile(OpenGLContext.profile) self._gl = QOpenGLContext.currentContext().versionFunctions(profile) if not self._gl: Logger.log("e", "Startup failed due to OpenGL initialization failing") QMessageBox.critical( None, "Failed to Initialize OpenGL", "Could not initialize OpenGL. This program requires OpenGL 2.0 or higher. Please check your video card drivers." ) sys.exit(1) # It would be nice to be able to not necessarily need OpenGL Framebuffer Object support, but # due to a limiation in PyQt, currently glReadPixels or similar methods are not available. # This means we can only get frame buffer contents through methods that indirectly call # those methods, in this case primarily QOpenGLFramebufferObject::toImage(), making us # hard-depend on Framebuffer Objects. if not self.hasFrameBufferObjects(): Logger.log( "e", "Starup failed, OpenGL does not support Frame Buffer Objects") QMessageBox.critical( None, "Critical OpenGL Extensions Missing", "Critical OpenGL extensions are missing. This program requires support for Framebuffer Objects. Please check your video card drivers." ) sys.exit(1) self._gl.initializeOpenGLFunctions() self._gpu_vendor = OpenGL.Vendor.Other vendor_string = self._gl.glGetString(self._gl.GL_VENDOR) if vendor_string is None: vendor_string = "Unknown" vendor_string = vendor_string.lower() if "nvidia" in vendor_string: self._gpu_vendor = OpenGL.Vendor.NVidia elif "amd" in vendor_string or "ati" in vendor_string: self._gpu_vendor = OpenGL.Vendor.AMD elif "intel" in vendor_string: self._gpu_vendor = OpenGL.Vendor.Intel self._gpu_type = self._gl.glGetString(self._gl.GL_RENDERER) if not self.hasFrameBufferObjects(): Logger.log( "w", "No frame buffer support, falling back to texture copies.") Logger.log("d", "Initialized OpenGL subsystems.") Logger.log("d", "OpenGL Version: %s", self._gl.glGetString(self._gl.GL_VERSION)) Logger.log("d", "OpenGL Vendor: %s", self._gl.glGetString(self._gl.GL_VENDOR)) Logger.log("d", "OpenGL Renderer: %s", self._gpu_type)
def opengl_vendor(): # pragma: no cover """Get the OpenGL vendor used. This returns a string such as 'nouveau' or 'Intel Open Source Technology Center'; or None if the vendor can't be determined. """ assert QApplication.instance() old_context = QOpenGLContext.currentContext() old_surface = None if old_context is None else old_context.surface() surface = QOffscreenSurface() surface.create() ctx = QOpenGLContext() ok = ctx.create() if not ok: log.init.debug("opengl_vendor: Creating context failed!") return None ok = ctx.makeCurrent(surface) if not ok: log.init.debug("opengl_vendor: Making context current failed!") return None try: if ctx.isOpenGLES(): # Can't use versionFunctions there return None vp = QOpenGLVersionProfile() vp.setVersion(2, 0) try: vf = ctx.versionFunctions(vp) except ImportError as e: log.init.debug("opengl_vendor: Importing version functions " "failed: {}".format(e)) return None if vf is None: log.init.debug("opengl_vendor: Getting version functions failed!") return None return vf.glGetString(vf.GL_VENDOR) finally: ctx.doneCurrent() if old_context and old_surface: old_context.makeCurrent(old_surface)
def __init__(self): super().__init__() fmt = QSurfaceFormat() fmt.setVersion(2, 0) fmt.setProfile(QSurfaceFormat.CompatibilityProfile) fmt.setStereo(False) fmt.setSwapBehavior(QSurfaceFormat.DoubleBuffer) self.setSurfaceType(QWindow.OpenGLSurface) self.context = QOpenGLContext() self.context.setFormat(fmt) if not self.context.create(): raise Exception("Unable to create context") self.create() self.setTitle("OpenGL")
def opengl_vendor(): # pragma: no cover """Get the OpenGL vendor used. This returns a string such as 'nouveau' or 'Intel Open Source Technology Center'; or None if the vendor can't be determined. """ assert QApplication.instance() override = os.environ.get('QUTE_FAKE_OPENGL_VENDOR') if override is not None: log.init.debug("Using override {}".format(override)) return override old_context = QOpenGLContext.currentContext() old_surface = None if old_context is None else old_context.surface() surface = QOffscreenSurface() surface.create() ctx = QOpenGLContext() ok = ctx.create() if not ok: log.init.debug("Creating context failed!") return None ok = ctx.makeCurrent(surface) if not ok: log.init.debug("Making context current failed!") return None try: if ctx.isOpenGLES(): # Can't use versionFunctions there return None vp = QOpenGLVersionProfile() vp.setVersion(2, 0) try: vf = ctx.versionFunctions(vp) except ImportError as e: log.init.debug("Importing version functions failed: {}".format(e)) return None if vf is None: log.init.debug("Getting version functions failed!") return None return vf.glGetString(vf.GL_VENDOR) finally: ctx.doneCurrent() if old_context and old_surface: old_context.makeCurrent(old_surface)
def opengl_vendor(): # pragma: no cover """Get the OpenGL vendor used. This returns a string such as 'nouveau' or 'Intel Open Source Technology Center'; or None if the vendor can't be determined. """ # We're doing those imports here because this is only available with Qt 5.4 # or newer. from PyQt5.QtGui import (QOpenGLContext, QOpenGLVersionProfile, QOffscreenSurface) assert QApplication.instance() old_context = QOpenGLContext.currentContext() old_surface = None if old_context is None else old_context.surface() surface = QOffscreenSurface() surface.create() ctx = QOpenGLContext() ok = ctx.create() if not ok: log.init.debug("opengl_vendor: Creating context failed!") return None ok = ctx.makeCurrent(surface) if not ok: log.init.debug("opengl_vendor: Making context current failed!") return None try: if ctx.isOpenGLES(): # Can't use versionFunctions there return None vp = QOpenGLVersionProfile() vp.setVersion(2, 0) vf = ctx.versionFunctions(vp) if vf is None: log.init.debug("opengl_vendor: Getting version functions failed!") return None return vf.glGetString(vf.GL_VENDOR) finally: ctx.doneCurrent() if old_context and old_surface: old_context.makeCurrent(old_surface)
def sanity_check(self): from PyQt5.QtGui import QOpenGLContext context = QOpenGLContext.currentContext() assert context assert threading.current_thread() is threading.main_thread() if self._opengl_context is not None: #assert context is self._opengl_context if context is not self._opengl_context: self.destroy() self.create()
def setContext(cls, major_version, minor_version, core = False, profile = None): new_format = QSurfaceFormat() new_format.setMajorVersion(major_version) new_format.setMinorVersion(minor_version) if core: profile_ = QSurfaceFormat.CoreProfile else: profile_ = QSurfaceFormat.CompatibilityProfile if profile is not None: profile_ = profile new_format.setProfile(profile_) new_context = QOpenGLContext() new_context.setFormat(new_format) success = new_context.create() if success: return new_context else: Logger.log("e", "Failed creating OpenGL context (%d, %d, core=%s)" % (major_version, minor_version, core)) return None
def hasExtension(cls, extension_name: str, ctx=None) -> bool: """Check to see if the current OpenGL implementation has a certain OpenGL extension. :param extension_name: :type{string} The name of the extension to query for. :param ctx: optionally provide context object to be used, or current context will be used. :return: True if the extension is available, False if not. """ if ctx is None: ctx = QOpenGLContext.currentContext() return ctx.hasExtension(bytearray(extension_name, "utf-8"))
def supportsVertexArrayObjects(cls, ctx = None): if ctx is None: ctx = QOpenGLContext.currentContext() result = False if cls.major_version == 4 and cls.minor_version >= 1: result = True if not result and cls.major_version > 4: result = True if not result and cls.hasExtension("GL_ARB_vertex_array_object", ctx = ctx): result = True cls.properties["supportsVertexArrayObjects"] = result return result
class WindowGL(QWindow): def __init__(self): super().__init__() fmt = QSurfaceFormat() fmt.setVersion(2, 0) fmt.setProfile(QSurfaceFormat.CompatibilityProfile) fmt.setStereo(False) fmt.setSwapBehavior(QSurfaceFormat.DoubleBuffer) self.setSurfaceType(QWindow.OpenGLSurface) self.context = QOpenGLContext() self.context.setFormat(fmt) if not self.context.create(): raise Exception("Unable to create context") self.create() self.setTitle("OpenGL") def exposeEvent(self, e): e.accept() if self.isExposed() and self.isVisible(): self.update() def makeCurrent(self): self.context.makeCurrent(self) def swapBuffers(self): self.context.swapBuffers(self) def resize(self, w, h): super().resize(w, h) self.makeCurrent() GL.glViewport(0, 0, w, h) def update(self): tri_size = 0.7 self.makeCurrent() GL.glClearColor(0, 0, 0, 0) GL.glClearDepth(1) GL.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT) GL.glBegin(GL.GL_TRIANGLES) GL.glVertex2f(0, tri_size) GL.glColor3f(1, 0, 0) GL.glVertex2f(-tri_size, -tri_size) GL.glColor3f(0, 1, 0) GL.glVertex2f(tri_size, -tri_size) GL.glColor3f(0, 0, 1) GL.glEnd() GL.glFlush() self.swapBuffers()
def beginRendering(self): if not self._initialized: self._initialize() self._gl.glViewport(0, 0, self._viewport_width, self._viewport_height) self._gl.glClearColor(self._background_color.redF(), self._background_color.greenF(), self._background_color.blueF(), self._background_color.alphaF()) self._gl.glClear(self._gl.GL_COLOR_BUFFER_BIT | self._gl.GL_DEPTH_BUFFER_BIT) if not QOpenGLContext.currentContext().format().renderableType() == QSurfaceFormat.OpenGLES: self._gl.glPointSize(2) self._solids_queue.clear() self._transparent_queue.clear() self._overlay_queue.clear() self._render_selection = True
def hasExtension(cls, extension_name: str, ctx=None) -> bool: """Check to see if the current OpenGL implementation has a certain OpenGL extension. :param extension_name: :type{string} The name of the extension to query for. :param ctx: optionally provide context object to be used, or current context will be used. :return: True if the extension is available, False if not. """ if ctx is None: ctx = QOpenGLContext.currentContext() if ctx is None: # We failed to get the current context. # The typing claims that this doesn't happen, yet results in the field indicate # that it does. See sentry crash CURA-87 return False return ctx.hasExtension(bytearray(extension_name, "utf-8"))
class GLWindow(QWindow): def __init__(self): super(GLWindow, self).__init__() self.title= "GLWindow" self.setGeometry(0, 0, 640, 480) self.setupUI() def setupUI(self): self.setSurfaceType(QWindow.OpenGLSurface) self.renderctxt = QOpenGLContext(self) self.renderctxt.setFormat(self.requestedFormat()) self.renderctxt.create() self.renderctxt.makeCurrent(self) self.glfunc = self.renderctxt.versionFunctions() self.glfunc.initializeOpenGLFunctions()
def supportsVertexArrayObjects(cls, ctx=None) -> bool: """Return if the current (or provided) context supports Vertex Array Objects :param ctx: (optional) context. """ if ctx is None: ctx = QOpenGLContext.currentContext() result = False if cls.major_version == 4 and cls.minor_version >= 1: result = True if not result and cls.major_version > 4: result = True if not result and cls.hasExtension("GL_ARB_vertex_array_object", ctx=ctx): result = True cls.properties["supportsVertexArrayObjects"] = result return result
def event(self, event): if event.type == Event.ViewActivateEvent: # FIX: on Max OS X, somehow QOpenGLContext.currentContext() can become None during View switching. # This can happen when you do the following steps: # 1. Start Cura # 2. Load a model # 3. Switch to Custom mode # 4. Select the model and click on the per-object tool icon # 5. Switch view to Layer view or X-Ray # 6. Cura will very likely crash # It seems to be a timing issue that the currentContext can somehow be empty, but I have no clue why. # This fix tries to reschedule the view changing event call on the Qt thread again if the current OpenGL # context is None. if Platform.isOSX(): if QOpenGLContext.currentContext() is None: Logger.log("d", "current context of OpenGL is empty on Mac OS X, will try to create shaders later") CuraApplication.getInstance().callLater(lambda e = event: self.event(e)) return if not self._xray_pass: # Currently the RenderPass constructor requires a size > 0 # This should be fixed in RenderPass's constructor. self._xray_pass = XRayPass.XRayPass(1, 1) self.getRenderer().addRenderPass(self._xray_pass) if not self._xray_composite_shader: self._xray_composite_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("XRayView"), "xray_composite.shader")) theme = Application.getInstance().getTheme() self._xray_composite_shader.setUniformValue("u_background_color", Color(*theme.getColor("viewport_background").getRgb())) self._xray_composite_shader.setUniformValue("u_error_color", Color(*theme.getColor("xray_error").getRgb())) self._xray_composite_shader.setUniformValue("u_outline_color", Color(*theme.getColor("model_selection_outline").getRgb())) if not self._composite_pass: self._composite_pass = self.getRenderer().getRenderPass("composite") self._old_layer_bindings = self._composite_pass.getLayerBindings() self._composite_pass.setLayerBindings(["default", "selection", "xray"]) self._old_composite_shader = self._composite_pass.getCompositeShader() self._composite_pass.setCompositeShader(self._xray_composite_shader) if event.type == Event.ViewDeactivateEvent: self.getRenderer().removeRenderPass(self._xray_pass) self._composite_pass.setLayerBindings(self._old_layer_bindings) self._composite_pass.setCompositeShader(self._old_composite_shader)
def opengl_vendor(): # pragma: no cover """Get the OpenGL vendor used. This returns a string such as 'nouveau' or 'Intel Open Source Technology Center'; or None if the vendor can't be determined. """ # We're doing those imports here because this is only available with Qt 5.4 # or newer. from PyQt5.QtGui import (QOpenGLContext, QOpenGLVersionProfile, QOffscreenSurface) assert QApplication.instance() assert QOpenGLContext.currentContext() is None surface = QOffscreenSurface() surface.create() ctx = QOpenGLContext() ok = ctx.create() assert ok ok = ctx.makeCurrent(surface) assert ok if ctx.isOpenGLES(): # Can't use versionFunctions there return None vp = QOpenGLVersionProfile() vp.setVersion(2, 0) vf = ctx.versionFunctions(vp) vendor = vf.glGetString(vf.GL_VENDOR) ctx.doneCurrent() return vendor
def initializeGL(self): super().initializeGL() self.camera.width = self.width() self.camera.height = self.height() self.camera._write() activate_opengl() if self._destroyed: return from PyQt5.QtGui import QOpenGLContext #print("INIT") ctx = self.context() assert ctx is QOpenGLContext.currentContext() #print("start initializeGL") if not self._initialized: add_opengl_context(ctx) self._initialized = True PINS.init.set() #print("end initializeGL") deactivate_opengl()
def __init__(self, args): super(TestApplication, self).__init__(args) print("EFFECTIVE QT VERSION : " + str(QT_VERSION_STR)) self.mainWin = QWidget() self.mainWin.resize(600, 600) self.mainWin.setWindowTitle('Minimal GL test') self.mainWidget = QOpenGLWidget() self.layout = QVBoxLayout(self.mainWin) self.layout.addWidget(self.mainWidget) self.mainWin.show() ctx = QOpenGLContext.currentContext() format = ctx.format() print("EFFECTIVE GL VERSION : " + str(ctx.format().version()))
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 __init__(self): profile = QOpenGLVersionProfile() profile.setVersion(2, 0) self._gl = QOpenGLContext.currentContext().versionFunctions(profile) if not self._gl: Logger.log("e", "Startup failed due to OpenGL initialization failing") QMessageBox.critical("Failed to Initialize OpenGL", "Could not initialize OpenGL. This program requires OpenGL 2.0 or higher. Please check your video card drivers.") sys.exit(1) # It would be nice to be able to not necessarily need OpenGL Framebuffer Object support, but # due to a limiation in PyQt, currently glReadPixels or similar methods are not available. # This means we can only get frame buffer contents through methods that indirectly call # those methods, in this case primarily QOpenGLFramebufferObject::toImage(), making us # hard-depend on Framebuffer Objects. if not self.hasFrameBufferObjects(): Logger.log("e", "Starup failed, OpenGL does not support Frame Buffer Objects") QMessageBox.critical("Critical OpenGL Extensions Missing", "Critical OpenGL extensions are missing. This program requires support for Framebuffer Objects. Please check your video card drivers.") sys.exit(1) self._gl.initializeOpenGLFunctions() self._gpu_vendor = OpenGL.Vendor.Other vendor_string = self._gl.glGetString(self._gl.GL_VENDOR) if vendor_string is None: vendor_string = "Unknown" vendor_string = vendor_string.lower() if "nvidia" in vendor_string: self._gpu_vendor = OpenGL.Vendor.NVidia elif "amd" in vendor_string or "ati" in vendor_string: self._gpu_vendor = OpenGL.Vendor.AMD elif "intel" in vendor_string: self._gpu_vendor = OpenGL.Vendor.Intel self._gpu_type = self._gl.glGetString(self._gl.GL_RENDERER) if not self.hasFrameBufferObjects(): Logger.log("w", "No frame buffer support, falling back to texture copies.") Logger.log("d", "Initialized OpenGL subsystems.") Logger.log("d", "OpenGL Version: %s", self._gl.glGetString(self._gl.GL_VERSION)) Logger.log("d", "OpenGL Vendor: %s", self._gl.glGetString(self._gl.GL_VENDOR)) Logger.log("d", "OpenGL Renderer: %s", self._gpu_type)
def hasExtension(self, extension): return QOpenGLContext.currentContext().hasExtension(extension)
class ViewerWindow(QWindow): instructions = """ --Key controls 0-9 - toggle data layers r - reset view parameters c - clip view t - view from top l - light/dark background = - increase point size - - decrease point size --Mouse controls drag shift + move - translate dataset scroll - scale dataset shift + scroll - change field of view ctrl + scroll - move far clipping plane alt + scroll - move near clipping plane ctrl + alt + scroll - move far and near clipping plane simultaniously """ def __init__(self, parent=None, **kwargs): super(ViewerWindow, self).__init__(parent) self.setSurfaceType(QWindow.OpenGLSurface) format = QSurfaceFormat() format.setVersion(3, 3) format.setProfile(QSurfaceFormat.CoreProfile) format.setStereo(False) format.setSwapBehavior(QSurfaceFormat.DoubleBuffer) format.setDepthBufferSize(24) format.setSamples(16) self.context = QOpenGLContext(self) self.context.setFormat(format) if not self.context.create(): raise Exception('self.context.create() failed') self.create() size = 720, 720 self.resize(*size) self.context.makeCurrent(self) self.hud_program = CrossHairProgram() self.default_view = np.eye(4, dtype=np.float32) self.view = self.default_view self.model = np.eye(4, dtype=np.float32) self.projection = np.eye(4, dtype=np.float32) self.layer_manager = LayerManager() self.visibility_toggle_listeners = [] self.multiview = True self.rotation = q.quaternion() self.scale = 0.6 self.translation = np.zeros(3) self.radius = 0.5 * min(*size) self.fov = 5. self.camera_position = -12. self.near_clip = .1 if 'near_clip' in kwargs: self.near_clip = kwargs['near_clip'] self.far_clip = 100. if 'far_clip' in kwargs: self.far_clip = kwargs['far_clip'] self.projection_mode = 'perspective' # 'orthographic' self.size = size self.bg_white = False self.viewpoint_dict = {} print((self.instructions)) def add_layer(self, layer): self.layer_manager.add_layer(layer) return layer # keeping this compatibility with older scripts def add_data_source(self, name, opts, points, normals=None, radii=None, intensity=None, category=None, zrange=None, **kwargs): if len(self.layer_manager.layers) == 0: self.layer_manager.add_layer(Layer(name='Default')) self.layer_manager.layers['Default'].add_data_source(name, opts, points, normals=normals, radii=radii, intensity=intensity, category=category, zrange=zrange, **kwargs) def add_data_source_line(self, name, coords_start, coords_end, **args): if len(self.layer_manager.layers) == 0: self.layer_manager.add_layer(Layer(name='Default')) self.layer_manager.layers['Default'].add_data_source_line(name, coords_start, coords_end, **args) def add_data_source_triangle(self, name, coords, normals, **args): if len(self.layer_manager.layers) == 0: self.layer_manager.add_layer(Layer(name='Default')) self.layer_manager.layers['Default'].add_data_source_triangle(name, coords, normals, **args) def run(self): self.initialize() self.show() def set_layer_visibility(self, name, is_visible): for listener in self.visibility_toggle_listeners: listener(name, is_visible) def center_view(self, center=None): if center is None: center = self.layer_manager.first.get_center() data_range = self.layer_manager.first.data_range self.data_width = data_range[0] self.data_height = data_range[2] self.translation = np.zeros(3) self.model = np.eye(4, dtype=np.float32) translate(self.model, -center[0], -center[1], -center[2]) for program in self.layer_manager.programs(): program.setUniform('u_model', self.model) self.update_view_matrix() def initialize(self): self.context.makeCurrent(self) gl.glDepthMask(gl.GL_TRUE) gl.glEnable(gl.GL_DEPTH_TEST) gl.glDepthFunc(gl.GL_LESS) self.set_bg() view_width, view_height = [x/self.radius for x in self.size] self.center_view() for program in self.layer_manager.programs(): program.setUniform('u_model', self.model) program.setUniform('u_view', self.view) program.setUniform('u_projection', self.projection) self.modelscale = .6* 2*min(2.*view_width/self.data_width, 2.*view_height/self.data_height) self.scale = self.modelscale self.update_view_matrix() self.last_mouse_pos = 0,0 self.on_resize(*self.size) def render(self): if not self.isExposed(): return self.context.makeCurrent(self) bits = 0 bits |= gl.GL_COLOR_BUFFER_BIT bits |= gl.GL_DEPTH_BUFFER_BIT bits |= gl.GL_STENCIL_BUFFER_BIT gl.glClear(bits) gl.glEnable(gl.GL_PROGRAM_POINT_SIZE) for program in self.layer_manager.programs(): if program.do_blending: if self.bg_white: gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_SRC_ALPHA) else: gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_ONE, gl.GL_SRC_ALPHA) else: gl.glDisable(gl.GL_BLEND) self.layer_manager.draw() if self.hud_program.is_visible: self.hud_program.draw() self.context.swapBuffers(self) def event(self, event): # print event.type() if event.type() == QEvent.UpdateRequest: self.render() return True return super(ViewerWindow, self).event(event) def exposeEvent(self, event): self.render() def resizeEvent(self, event): size = event.size() self.on_resize(size.width(), size.height()) self.render() def update_view_matrix(self): self.view = np.eye(4, dtype=np.float32) translate(self.view, self.translation[0], self.translation[1], self.translation[2] ) scale(self.view, self.scale, self.scale, self.scale) self.view = self.view.dot( np.array(q.matrix(self.rotation), dtype=np.float32) ) # translate(self.view, -self.translation[0], -self.translation[1], -self.translation[2] ) translate(self.view, 0,0, self.camera_position) for program in self.layer_manager.programs(): program.setUniform('u_view', self.view) if program.draw_type == 'points': program.setUniform('u_model_scale', self.scale) def update_projection_matrix(self): view_width, view_height = [x/self.radius for x in self.size] if self.projection_mode == 'orthographic': self.projection = ortho(-view_width, view_width, -view_height, view_height, self.near_clip, self.far_clip) elif self.projection_mode == 'perspective': self.projection = perspective(self.fov, view_width / float(view_height), self.near_clip, self.far_clip) for program in self.layer_manager.programs(): program.setUniform('u_projection', self.projection) def screen2view(self, x,y): width, height = self.size # print (x-width/2.)/self.radius, ((height-y)-height/2.)/self.radius return (x-width/2.)/self.radius, ((height-y)-height/2.)/self.radius def set_bg(self): gl.glEnable(gl.GL_BLEND) gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA) if self.bg_white: gl.glClearColor(0.95,0.95,0.95,1) # gloo.set_state('translucent', clear_color=np.array([1,1,1,1]) ) else: gl.glClearColor(0.05,0.05,0.05,1) # gloo.set_state('translucent', clear_color=np.array([0.15,0.15,0.15,1]) ) def keyPressEvent(self, event): key = event.key() repeat = event.isAutoRepeat() if key == Qt.Key_R: self.view = np.eye(4, dtype=np.float32) self.rotation = q.quaternion() self.scale = self.modelscale self.camera_position = -12. self.near_clip = 2. self.far_clip = 100. self.center_view() self.update_projection_matrix() elif key == Qt.Key_Minus: for layer in self.layer_manager: if layer.is_visible: for program in layer: if program.draw_type == 'points': if (program.is_visible and self.multiview) or not self.multiview: program.setUniform('u_point_size', program.uniforms['u_point_size']/1.2) elif key == Qt.Key_Equal: for layer in self.layer_manager: if layer.is_visible: for program in layer: if program.draw_type == 'points': if (program.is_visible and self.multiview) or not self.multiview: program.setUniform('u_point_size', program.uniforms['u_point_size']*1.2) elif key == Qt.Key_B: for program in self.layer_manager.programs(): if program.is_visible and program.draw_type == 'points': program.do_blending = not program.do_blending elif key == Qt.Key_C: self.near_clip = -self.camera_position - 0.1 self.far_clip = -self.camera_position + 0.1 self.update_projection_matrix() elif key == Qt.Key_T: self.rotation = q.quaternion() self.update_view_matrix() elif key == Qt.Key_P: if self.projection_mode == 'perspective': self.projection_mode = 'orthographic' else: self.projection_mode = 'perspective' self.update_projection_matrix() elif key == Qt.Key_L: self.bg_white = not self.bg_white self.set_bg() elif Qt.Key_0 <= key <= Qt.Key_9: i = int(chr(key))-1 layers = [item for item in self.layer_manager.layers.items()] if i < len(layers): name, layer = layers[i] self.set_layer_visibility(name,layer.toggle()) # if self.multiview: # self.set_layer_visibility(list(self.data_programs.keys())[i], not list(self.data_programs.values())[i].is_visible) # else: # for pi, prog in enumerate(self.data_programs.values()): # prog.is_visible = False # if pi == i: # prog.is_visible = True self.update() def on_resize(self, size_x, size_y): gl.glViewport(int(0), int(0), int(size_x), int(size_y)) self.radius = 0.5 * min(size_x, size_y) self.size = size_x, size_y self.update_projection_matrix() def wheelEvent(self, event): # def on_mouse_wheel(self, window, offset_x, offset_y): ticks = float(event.angleDelta().y()+event.angleDelta().x())/50 modifiers = event.modifiers() if modifiers == Qt.ControlModifier | Qt.AltModifier: # if modifiers == Qt.ShiftModifier: ticks /= 30 self.near_clip -= ticks self.far_clip -= ticks self.update_projection_matrix() elif modifiers == Qt.AltModifier: # if modifiers == Qt.ShiftModifier: ticks /= 30 new = max(0.1,self.near_clip - ticks) if new <= self.far_clip: self.near_clip = new self.update_projection_matrix() elif modifiers == Qt.ControlModifier: # if modifiers == Qt.ShiftModifier: ticks /= 30 new = min(1000,self.far_clip - ticks) if new >= self.near_clip: self.far_clip = new self.update_projection_matrix() elif modifiers == Qt.ShiftModifier: if self.projection_mode == 'perspective': old_fov = self.fov # do `dolly zooming` so that world appears at same size after canging fov self.fov = max(5.,self.fov + ticks) self.fov = min(120.,self.fov) self.camera_position = self.camera_position * (math.tan(math.radians(old_fov)/2.)) / (math.tan(math.radians(self.fov)/2.)) self.update_projection_matrix() self.update_view_matrix() elif modifiers == Qt.MetaModifier: self.camera_position += ticks/10 self.update_view_matrix() else: self.scale *= ticks/10 + 1. # self.camera_position += ticks/10 self.update_view_matrix() self.update() def mouseMoveEvent(self, event): modifiers = event.modifiers() buttons = event.buttons() pos_x, pos_y = event.x(), event.y() if Qt.ShiftModifier == modifiers: x0,y0 = self.last_mouse_pos x1,y1 = pos_x, pos_y dx, dy = (x1-x0), (y1-y0) #scale to zero plane in projection frustrum if self.projection_mode == 'perspective': scale = -self.camera_position * math.tan(math.radians(self.fov/2.)) dx, dy = scale*dx, scale*dy #multiply with inverse view matrix and apply translation in world coordinates self.translation += np.array([dx/self.radius, -dy/self.radius, 0., 0.]).dot( np.linalg.inv(self.view)) [:3] elif self.projection_mode == 'orthographic': # this is not fully correct self.translation += self.modelscale * np.array([dx, -dy, 0., 0.]).dot( np.linalg.inv(self.view)) [:3] self.hud_program.is_visible = True elif Qt.LeftButton == buttons: x0,y0 = self.screen2view(*self.last_mouse_pos) x1,y1 = self.screen2view(pos_x, pos_y) v0 = q.arcball(x0, y0) v1 = q.arcball(x1, y1) self.rotation = q.product(v1, v0, self.rotation) self.hud_program.is_visible = True else: self.hud_program.is_visible = False self.update_view_matrix() self.update() self.last_mouse_pos = pos_x, pos_y def update(self): self.render()
class OpenGLWindow(QWindow): def __init__(self, parent=None): super(OpenGLWindow, self).__init__(parent) self.m_update_pending = False self.m_animating = False self.m_context = None self.m_device = None self.m_gl = None self.logger = None self.setSurfaceType(QWindow.OpenGLSurface) def initialize(self, gl): pass def setAnimating(self, animating): self.m_animating = animating if animating: self.renderLater() def renderLater(self): if not self.m_update_pending: self.m_update_pending = True QGuiApplication.postEvent(self, QEvent(QEvent.UpdateRequest)) def paint(self, painter): pass def render(self, gl): pass def addGlFunctuins(self, GL, functions): for function, arguments in functions.items(): GL[function].restype = None GL[function].argtypes = arguments setattr(self.m_gl, function, GL[function]) @exitOnKeyboardInterrupt def renderNow(self): if not self.isExposed(): return self.m_update_pending = False needsInitialize = False if self.m_context is None: self.m_context = QOpenGLContext(self) self.m_context.setFormat(self.requestedFormat()) self.m_context.create() needsInitialize = True self.m_context.makeCurrent(self) if needsInitialize: # Sorry, no support for higher versions for now. profile = QOpenGLVersionProfile() profile.setVersion(2, 0) self.m_gl = self.m_context.versionFunctions(profile) self.m_gl.initializeOpenGLFunctions() #print(self.m_context.hasExtension('GL_EXT_framebuffer_object')) #print(self.m_context.hasExtension('GL_ARB_texture_float')) #print(*sorted(self.m_context.extensions()), sep='\n') # Small hack. Guess noone mind? import ctypes import ctypes.util GL = ctypes.CDLL(ctypes.util.find_library('GL')) self.addGlFunctuins(GL, { 'glFramebufferTexture2D': (ctypes.c_uint, ctypes.c_uint, ctypes.c_uint, ctypes.c_uint, ctypes.c_int) }) self.logger = QOpenGLDebugLogger() self.logger.initialize() self.logger.loggedMessages() self.logger.messageLogged.connect(self.handleLoggedMassage) self.logger.startLogging() self.initialize(self.m_gl) if not self.m_device: self.m_device = QOpenGLPaintDevice() self.m_gl.glClear(self.m_gl.GL_COLOR_BUFFER_BIT | self.m_gl.GL_DEPTH_BUFFER_BIT); self.m_device.setSize(self.size()) painter = QPainter(self.m_device) painter.beginNativePainting() self.render(self.m_gl) painter.endNativePainting() self.paint(painter) self.m_context.swapBuffers(self) if self.m_animating: self.renderLater() def handleLoggedMassage(self, message): # This three really annoyng and brings no useful info =\ if not (message.message().find('Use glDrawRangeElements() to avoid this.') > -1 or message.message().find('CPU mapping a busy miptree') > -1 or message.message().find('Flushing before mapping a referenced bo.') > -1 ): print(message.message().strip()) def event(self, event): if event.type() == QEvent.UpdateRequest: self.renderNow() return True return super(OpenGLWindow, self).event(event) def exposeEvent(self, event): self.renderNow() def resizeEvent(self, event): self.renderNow()
def renderNow(self): if not self.isExposed(): return self.m_update_pending = False needsInitialize = False if self.m_context is None: self.m_context = QOpenGLContext(self) self.m_context.setFormat(self.requestedFormat()) self.m_context.create() needsInitialize = True self.m_context.makeCurrent(self) if needsInitialize: # Sorry, no support for higher versions for now. profile = QOpenGLVersionProfile() profile.setVersion(2, 0) self.m_gl = self.m_context.versionFunctions(profile) self.m_gl.initializeOpenGLFunctions() #print(self.m_context.hasExtension('GL_EXT_framebuffer_object')) #print(self.m_context.hasExtension('GL_ARB_texture_float')) #print(*sorted(self.m_context.extensions()), sep='\n') # Small hack. Guess noone mind? import ctypes import ctypes.util GL = ctypes.CDLL(ctypes.util.find_library('GL')) self.addGlFunctuins(GL, { 'glFramebufferTexture2D': (ctypes.c_uint, ctypes.c_uint, ctypes.c_uint, ctypes.c_uint, ctypes.c_int) }) self.logger = QOpenGLDebugLogger() self.logger.initialize() self.logger.loggedMessages() self.logger.messageLogged.connect(self.handleLoggedMassage) self.logger.startLogging() self.initialize(self.m_gl) if not self.m_device: self.m_device = QOpenGLPaintDevice() self.m_gl.glClear(self.m_gl.GL_COLOR_BUFFER_BIT | self.m_gl.GL_DEPTH_BUFFER_BIT); self.m_device.setSize(self.size()) painter = QPainter(self.m_device) painter.beginNativePainting() self.render(self.m_gl) painter.endNativePainting() self.paint(painter) self.m_context.swapBuffers(self) if self.m_animating: self.renderLater()
class OpenGLWindow(QWindow): def __init__(self, parent=None): super(OpenGLWindow, self).__init__(parent) self.m_update_pending = False self.m_animating = False self.m_context = None self.m_gl = None self.setSurfaceType(QWindow.OpenGLSurface) def initialize(self): pass def setAnimating(self, animating): self.m_animating = animating if animating: self.renderLater() def renderLater(self): if not self.m_update_pending: self.m_update_pending = True QGuiApplication.postEvent(self, QEvent(QEvent.UpdateRequest)) def renderNow(self): if not self.isExposed(): return self.m_update_pending = False needsInitialize = False if self.m_context is None: self.m_context = QOpenGLContext(self) self.m_context.setFormat(self.requestedFormat()) self.m_context.create() needsInitialize = True self.m_context.makeCurrent(self) if needsInitialize: self.m_gl = self.m_context.versionFunctions() self.m_gl.initializeOpenGLFunctions() self.initialize() self.render(self.m_gl) self.m_context.swapBuffers(self) if self.m_animating: self.renderLater() def event(self, event): if event.type() == QEvent.UpdateRequest: self.renderNow() return True return super(OpenGLWindow, self).event(event) def exposeEvent(self, event): self.renderNow() def resizeEvent(self, event): self.renderNow()
def hasExtension(cls, extension_name, ctx = None): if ctx is None: ctx = QOpenGLContext.currentContext() return ctx.hasExtension(bytearray(extension_name, "utf-8"))
def event(self, event): modifiers = QApplication.keyboardModifiers() ctrl_is_active = modifiers & Qt.ControlModifier shift_is_active = modifiers & Qt.ShiftModifier if event.type == Event.KeyPressEvent and ctrl_is_active: amount = 10 if shift_is_active else 1 if event.key == KeyEvent.UpKey: self.setLayer(self._current_layer_num + amount) return True if event.key == KeyEvent.DownKey: self.setLayer(self._current_layer_num - amount) return True if event.type == Event.ViewActivateEvent: # FIX: on Max OS X, somehow QOpenGLContext.currentContext() can become None during View switching. # This can happen when you do the following steps: # 1. Start Cura # 2. Load a model # 3. Switch to Custom mode # 4. Select the model and click on the per-object tool icon # 5. Switch view to Layer view or X-Ray # 6. Cura will very likely crash # It seems to be a timing issue that the currentContext can somehow be empty, but I have no clue why. # This fix tries to reschedule the view changing event call on the Qt thread again if the current OpenGL # context is None. if Platform.isOSX(): if QOpenGLContext.currentContext() is None: Logger.log("d", "current context of OpenGL is empty on Mac OS X, will try to create shaders later") CuraApplication.getInstance().callLater(lambda e=event: self.event(e)) return # Make sure the SimulationPass is created layer_pass = self.getSimulationPass() self.getRenderer().addRenderPass(layer_pass) # Make sure the NozzleNode is add to the root nozzle = self.getNozzleNode() nozzle.setParent(self.getController().getScene().getRoot()) nozzle.setVisible(False) Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged) self._onGlobalStackChanged() if not self._simulationview_composite_shader: self._simulationview_composite_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SimulationView"), "simulationview_composite.shader")) theme = Application.getInstance().getTheme() self._simulationview_composite_shader.setUniformValue("u_background_color", Color(*theme.getColor("viewport_background").getRgb())) self._simulationview_composite_shader.setUniformValue("u_outline_color", Color(*theme.getColor("model_selection_outline").getRgb())) if not self._composite_pass: self._composite_pass = self.getRenderer().getRenderPass("composite") self._old_layer_bindings = self._composite_pass.getLayerBindings()[:] # make a copy so we can restore to it later self._composite_pass.getLayerBindings().append("simulationview") self._old_composite_shader = self._composite_pass.getCompositeShader() self._composite_pass.setCompositeShader(self._simulationview_composite_shader) elif event.type == Event.ViewDeactivateEvent: self._wireprint_warning_message.hide() Application.getInstance().globalContainerStackChanged.disconnect(self._onGlobalStackChanged) if self._global_container_stack: self._global_container_stack.propertyChanged.disconnect(self._onPropertyChanged) self._nozzle_node.setParent(None) self.getRenderer().removeRenderPass(self._layer_pass) self._composite_pass.setLayerBindings(self._old_layer_bindings) self._composite_pass.setCompositeShader(self._old_composite_shader)