BestMPRBaseVtk-003-修改工程,搬运官方代码并尝试理解-2

简介: BestMPRBaseVtk-003-修改工程,搬运官方代码并尝试理解-2

image.png修改工程,搬运官方代码并尝试理解-2

接着上篇,今天接着搞官方的源码,太难了,真想回家卖红薯去,你们说靠卖红薯可以养家糊口吗?


文章目录


修改工程,搬运官方代码并尝试理解-2

1 setRenderWindow

1.1vtkRenderWindow

1.2 vtkGenericOpenGLRenderWindow

1.3 QVTKRenderWindowAdapter

2 OpenGL相关

2.1 上下文

3 QSurfaceFormat

4 event

5 initializeGL

5.1 Q_ASSERT

6 paintGL

6.1makeCurrent

☞ 源码

关键字: Qt 插件、context、renderwindow、QSurfaceFormat、双缓冲


1 setRenderWindow

今天就搞这个 setRenderWindow在官方的代码里面, 大致就是设置一个用来渲染的窗口,并完成所有的初始化工作。


setRenderWindow有两个setRenderWindow函数,但是最终都会汇到一个上面,其中一个感觉就是做了个类型转换。先看一个简单的,代码如下

void BPPMPRWidget::setRenderWindow(vtkRenderWindow *win)
{
    //做类型转换
    auto gwin = vtkGenericOpenGLRenderWindow::SafeDownCast(win);
    if(win != nullptr && gwin == nullptr)
    {
        qDebug() << "QVTKOpenGLNativeWidget requires a `vtkGenericOpenGLRenderWindow`. `"
                 << win->GetClassName() << "` is not supported.";
    }
    this->setRenderWindow(gwin);
}

是不是,这个就是做了一个类型转换呢,就是把一个vtkRenderWindow类型的指针转换成一个vtkGenericOpenGLRenderWindow类型的指针,完了在传给另一个setRenderWindow就是下面的这个

void BPPMPRWidget::setRenderWindow(vtkGenericOpenGLRenderWindow *win)
{
    if(this->RenderWindow == win)               //判断当前窗口是不是传进来的,是就返回不是继续
    {
        return;
    }
    if(this->RenderWindowAdapter)               // 这将释放所有与旧窗口相关的OpenGL资源
    {
        this->makeCurrent();
        this->RenderWindowAdapter.reset(nullptr);
    }
    this->RenderWindow = win;
    if(this->RenderWindow)
    {
        this->RenderWindow->SetReadyForRendering(false);
        //如果没有提供交互器,我们默认将创建一个
        if(!this->RenderWindow->GetInteractor())
        {
            vtkNew<QVTKInteractor> iren;                //创建一个默认交互器
            this->RenderWindow->SetInteractor(iren);    //为RenderWindow添加交互器
            iren->Initialize();                         //交互器初始化
            //设置交互器默认样式
            vtkNew<vtkInteractorStyleTrackballCamera> style;
            iren->SetInteractorStyle(style);
        }
        if(this->isValid())
        {
            this->makeCurrent();
            this->initializeGL();
            this->updateSize();
        }
    }
}

1.1vtkRenderWindow


为渲染器创建一个渲染窗口。


1.2 vtkGenericOpenGLRenderWindow


一个与平台无关的渲染窗口。vtkGenericOpenGLRenderWindow提供了一个框架来实现一个渲染窗口使用自己的OPenGL上下文和绘制。


1.3 QVTKRenderWindowAdapter


帮助管理Qt上下文和其他OpenGL组件。


QVTKRenderWindowAdapter是一个内部类,被QVTKOpenGLNativeWidget和QVTKOpenGLWindow用来管理渲染使用vtkGenericOpenGLRenderWindow通过Qt创建OpenGL上下文。


2 OpenGL相关

2.1 上下文

OpenGL Context,中文解释就是OpenGL的上下文,OpenGL只是图形API,他没有窗口的支持,我们一般使用glut或glfw来创建窗口,然后在这个窗口中绘制。所以上下文的意思就是OpenGL的作用范围,在这里可以先简单的理解为就是这个窗口,也就是说,如果我们要使用OpenGL,需要先为它创建一个窗口,当然OpenGL 的Context不只是这个窗口,这个窗口我们可以可以理解为OpenGL的default framebuffer,所以Context还包含关于这个framebuffer的一些参数设置信息,具体内容可以查看OpenGL的Context的结构体。


参考链接:


https://www.cnblogs.com/xin-lover/p/9453760.html


https://blog.csdn.net/csxiaoshui/article/details/79032464


3 QSurfaceFormat

代码如下,这里可以看一下,官方代码中有一个返回一个QSurfaceFormat类型的值,这里重点研究一下这个东西

QSurfaceFormat BPPMPRWidget::defaultFormat(bool stereo_capable)
{
    return QVTKRenderWindowAdapter::defaultFormat(stereo_capable);
}

QSurfaceFormat代表QSurface的一种格式,包括颜色缓冲(RGBA缓冲)、深度缓冲、多重采样数量等。而QSurface是一个可渲染的抽象类,继承自QOffscreenSurface 和QWindow


· size():设置接口大小


· format():设置渲染的特殊属性。


参考资料


https://www.cnblogs.com/myboat/p/11183704.html


https://blog.csdn.net/zchl159/article/details/51005467


4 event


这个我的理解就是获取Qt事件,把Qt时间传给vtk,完了又调用了父类的event

bool BPPMPRWidget::event(QEvent *evt)                       
{
    if(this->RenderWindowAdapter)
    {
        this->RenderWindowAdapter->handleEvent(evt);
    }
    return this->Superclass::event(evt);
}

5 initializeGL


这个重写了父类的initializeGL,函数开始还是先调用了父类的initializeGL

void BPPMPRWidget::initializeGL()
{
    this->Superclass::initializeGL();
    if(this->RenderWindow)
    {
        Q_ASSERT(this->RenderWindowAdapter.data() == nullptr);              //测试代码
        this->RenderWindowAdapter.reset(new QVTKRenderWindowAdapter(this->context(),this->RenderWindow,this));  //重置
        this->RenderWindowAdapter->setDefaultCursor(this->defaultCursor());         //设置默认光标
        this->RenderWindowAdapter->setEnableHiDPI(this->EnableHiDPI);               //设置HiDPI
        this->RenderWindowAdapter->setUnscaledDPI(this->UnscaledDPI);               //设置默认DPI
    }
    this->connect(this->context(),&QOpenGLContext::aboutToBeDestroyed,this,&BPPMPRWidget::cleanupContext,static_cast<Qt::ConnectionType>(Qt::UniqueConnection | Qt::DirectConnection)); //连接信号槽
}

5.1 Q_ASSERT


Prints a warning message containing the source code file name and line number if test is false.


Q_ASSERT() is useful for testing pre- and post-conditions during development. It does nothing if QT_NO_DEBUG was defined during compilation.


如果test为假,则打印包含源代码文件名和行号的警告消息。


Q_ASSERT()对于在开发期间测试前置和后置条件非常有用。 如果QT_NO_DEBUG是在编译期间定义的,那么它什么也不做。


6 paintGL

paintGL函数在运行时调用了父类的paintGL。完了调用了自己的paint函数。和面完成了OpenGL的设置。

void BPPMPRWidget::paintGL()
{
    this->Superclass::paintGL();
    if(this->RenderWindow)
    {
        Q_ASSERT(this->RenderWindowAdapter);
        this->RenderWindowAdapter->paint();
        this->makeCurrent();                    //在大多数情况下,没有必要调用这个函数,因为在调用paintGL()之前会自动调用它。
        QOpenGLFunctions_3_2_Core* f = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_2_Core>();
        if(f)
        {
            const QSize deviceSize = this->size() * this->devicePixelRatioF();
            this->RenderWindowAdapter->blit(this->defaultFramebufferObject(),GL_COLOR_ATTACHMENT0,QRect(QPoint(0,0),deviceSize));
        }
    }
    else
    {
        QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
        f->glClearColor(1.0f,1.0f,1.0f,1.0f);
        f->glClear(GL_COLOR_BUFFER_BIT);
    }
}

6.1makeCurrent

Prepares for rendering OpenGL content for this widget by making the corresponding context current and binding the framebuffer object in that context.


It is not necessary to call this function in most cases, because it is called automatically before invoking paintGL().


通过将相应的上下文设置为当前并在该上下文中绑定framebuffer对象,为这个小部件呈现OpenGL内容做准备。


在大多数情况下,没有必要调用这个函数,因为在调用paintGL()之前会自动调用它。


☞ 源码

源码链接:GitHub仓库自取


使用方法:☟☟☟

image.png

目录
相关文章
|
21天前
|
负载均衡 数据库 开发工具
|
4月前
|
运维 Kubernetes 安全
阿里云云效操作报错合集之发布报错,该怎么进构建环境
本合集将整理呈现用户在使用过程中遇到的报错及其对应的解决办法,包括但不限于账户权限设置错误、项目配置不正确、代码提交冲突、构建任务执行失败、测试环境异常、需求流转阻塞等问题。阿里云云效是一站式企业级研发协同和DevOps平台,为企业提供从需求规划、开发、测试、发布到运维、运营的全流程端到端服务和工具支撑,致力于提升企业的研发效能和创新能力。
|
5月前
|
Ubuntu 网络安全 开发工具
想要拥有自己的代码仓库服务?看这一篇就够了
【5月更文挑战第15天】本文档介绍了在Ubuntu 20上搭建Git服务器的步骤,包括参照官方安装指南、设置EXTERNAL_URL为IP地址以跳过HTTPS,以及解决可能的问题如重启gitlab服务。文章总结了Git服务器安装的简易性,但指出可能遇到的CICD问题,并建议可考虑使用GitHub或GitLab。
83 4
|
12月前
|
小程序 前端开发
【易售小程序项目】项目介绍、小程序页面展示与系列文章集合
【易售小程序项目】项目介绍、小程序页面展示与系列文章集合
113 2
|
5月前
|
缓存 NoSQL 数据库
总结 做项目的一点自己的想法 在开发中我觉得可以修改的地方
总结 做项目的一点自己的想法 在开发中我觉得可以修改的地方
32 1
|
11月前
|
JavaScript 前端开发 Cloud Native
云his源码 多院区集团化的全院HIS系统源代码
系统利用云计算平台的技术优势,建立统一的云HIS、云病历、云LIS,有效实现实现协同门诊、住院、药房药库管理、双向转诊转检、远程会诊诊断及医疗数据共享与交换,解决数据重复采集及信息孤岛等问题,为实现区域协同医疗卫生信息化平台奠定了基础。 系统技术特点:采用前后端分离架构,前端由Angular语言、JavaScript开发;后端使用Java语言开发,适用于二级医院、基层医疗机构,可作为区域HIS使用,经扩展后能够应用于医联体/医共体。 云病历:完全满足和符合国家电子病历评级标准。三级质控,病历留痕,续打,批注
|
自然语言处理 编译器 程序员
【跟着操作就行了】手把手教你 编译+链接 程序环境教程
【跟着操作就行了】手把手教你 编译+链接 程序环境教程
96 0
|
Kubernetes 前端开发 Go
上篇:带你手工体验从写代码、编译、打包镜像、部署到K8S的全过程
上篇:带你手工体验从写代码、编译、打包镜像、部署到K8S的全过程
407 0
|
中间件 测试技术
NestJS 7.x 折腾记: (1) 项目初始化及常规提交门禁加入
系列常规操作,没兴趣的可以跳过这篇水文. 写过Angular 2+的小伙伴会有一种天然的熟悉感. 因为Nest基本就是同一个思想模式搞得~~
225 0
|
XML IDE Java
阅读Spring源码第一步:源码编译与创建调试入口
 Spring开源框架经过很长时间的发展,各个模块均已成熟,一个常识就是一个可靠,可扩展的高性能框架,它的代码行数是相当可观的,我用static插件简略测算了一下,Spring的源码有100多万行,可以想象其中的调用逻辑是相当复杂的,所以将Spring源码下载到本地再编译的话,我们就可以通过IDE的debug来来到抽丝剥茧分析源码的目的,并且我们可以很方便的使用idea来查看调用栈,方法的调用关系也就比较明了了。
阅读Spring源码第一步:源码编译与创建调试入口
下一篇
无影云桌面