前言

  毕设说实话并没有花费太多的时间投入进去,毕竟工作上的事情也很多。
  最初聪哥是和我说直接帮我解决毕设的问题的,我的毕设其实和大学打的创业比赛的那套 WebGL 模型预览网站的东西是一样。
  当时报备毕设的时候就想着应付一下,不打算花费太多的心神。

  后来师兄的工作室开发 Zeus 三维素材预览软件。
  于是我就掺和了进去,为了实现跨DCC实现三维预览,我这里也借助了 WebGL 的功能,并且开发了 CefWidget
  随着开发的深入,后面我也想着不如就把这个资产浏览器当做自己的毕设好了。
  但是毕竟代码都是师弟他们弄得,我就过来打打辅助而已,怎么可以直接拿别人的代码当毕设呢?
  所以我最初打算分成两条线开发,我自己也写一个资产管理的软件。
  于是那段时间开始开发 Qt 数据双向绑定的库,打算拿资产开发作为这个库最终效果的测试。
  为了搞这个,又去研究 Vue.js 的 MVVM 架构,去学习了解了 Flux 设计模式。(搞了一大通,最后其实一脸懵逼)

  后来双向数据绑定的开发难产(现在也没有完全搞完,思路还改了一波),自己开发资产库的计划就一拖再拖。
  最后临近5月份,老师催着要交论文了,没有办法。
  我只好改变思路,直接做毕设差不多的网站出来算了。

  想到做网站,需要用到服务器,要做全栈开发,突然觉得可以去学学 Go 开发,也挺好的,最近各路神仙大佬都推荐学习这个。
  于是就自己学 Go 来做一下后端开发了。所以就开始了一个星期突击学习速成毕设的过程。

技术选型

  决定要独自搞毕设之后,首先就要进行技术选项评估了。
  后台毋庸置疑选用 Go 来实现了,前端还让我纠结了好一会。
  想到之前还在研究 Vuex 的全局状态管理是如何实现的,于是我打算这次前端也用 Vue 来搭建吧。
  因为赶时间,就直接用后台框架去 vue-element-admin 做了,结果是个大坑。
  服务器端因为用来了 宝塔面板 , 可以快速建站,搭建 MySql 数据库也非常简单。
  由于网站搭建的内容不太够,所以又拿了之前研究的 CefWidget 跨 DCC 浏览器进行凑数。

  下面就把论文的部分整理出来,相当于水了一篇文章。

摘要

  基于WebGL技术驱动的三维网站,实现跨 Digital Content Creation软件的三维资产库。基于 Go Iris 框架搭建软件的后台系统,进行服务器端的数据交互,通过腾讯云的 Linux服务器上搭建 MySql 数据库进行数据保存。通过前端框架 Vue Element Admin 搭建后台管理系统的前端页面,实现线上模型素材的管理。通过 Python Cefpython3 库实现浏览器在 Qt 框架下的嵌入,实现将WebGL技术封装到 Digital Content Creation软件中,最后使用 Python 的 Qt 框架搭建出可以在不同软件平台下启动的三维资产库客户端。

  由于 Digital Content Creation软件下的 Python 经过了特殊的修改,并不支持一些Cython 编译的程序库,因此这里将 Cefpython3 实现的浏览器通过 Socket 套接字编程搭建Python服务器端口来进行进程通信,利用 Cef 的嵌入原理将浏览器嵌入到Qt图形界面当中。

关键字:WebGL,Vue, Go, Python,Qt, CEF

1.绪论

1.1 课题简介

  WebGL基于 OpenGL ES2.0 的标准在网页浏览器中实现三维图形渲染的效果,因为其所具备跨平台交互体验好的基础,目前在网页开发中越来越受到青睐。

  这里我们基于 Three.js 使用 WebGL 技术搭建出可在网页上预览三维模型的编辑器,Three.js 是开源的 WebGL 框架,内置了许多关于三维操作的函数,可以极大简化开发难度。

  网站的搭建基于前端框架 Vue.js 搭建出后台数据管理系统,Vue.js 是目前主流的网页渲染框架,其技术开发借鉴了 Angualr.js 和 React.js 兼具模板引擎和js拆分功能。目前Vue的社区非常活跃,在前端开发中具有不可磨灭的影响。

  后台服务端使用 Golang 语言的 Iris 框架,使用 mysql 数据库进行后台数据存储。Golang语言由Google开发并维护的编程语言,是目前服务器后端开发中的后起之秀,由于其性能优秀,使用简单,已经越来越广泛地运用到各种编程的领域里面。

  桌面客户端这是基于跨平台的 Qt 框架利用 Python 绑定,使用 python 进行编写,因为目前各种 Digital Content Creation(以下简称 DCC ) 软件大部分都是 Qt 框架开发的,都支持 Python Qt 图形化界面开编写软件的工具,通过 Python Qt 编写图形化界面就可以将我们的 WebGL 网站嵌入到 DCC软件中。

2.Vue前端页面开发

2.1 Vue 框架介绍

  Vue.js是一套构建用户界面的渐进式框架,采用自底向上增量开发的设计,通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

  Vue.js 是目前主流的前端三大框架之一,比起原生JavaScript,Vue不再需要让用户操作DOM元素,解放了用户的双手,让程序员可以更多时间去关注业务逻辑,并且Vue使用了MVVM模式实现了数据的双向绑定,这样数据的更新操作更加简单使用,开发效率更高。

  在使用 Vue .js 之前需要先安装 node.js 引擎,node.js 借助谷歌chromium V8引擎实现JavaScript 脱离浏览器运行,让 JavaScript 的开发边界极大扩大了,因此基于 node.js引擎让不仅仅诞生了服务于后端的 express 框架甚至可以用 electron 框架进行桌面开发。

  安装了 node.js 之后就可以在系统的命令行中访问 npm 模块管理器,通过 npm 可以下载 JavaScript 生态下社区所贡献的各种不同的模块,极大丰富了编程世界的活力。

  Vue 也是基于 node.js 对 .vue 文件进行解析编译,然后通过 Webpack 工具将开发好的页面精简打包成一个静态网站。

  可以通过 npm 安装 vue-cli 来快速配置 vue ,直接通过 npm install –global vue-cli 即可,然后就可以使用 vue init 命令初始化一个简单的 Vue 工程。

  Vue工程已经配置好所有的 JavaScript 依赖库,以及 webpack 等工具的配置,查看 package.json 可以看到 dev 命令已经配置了 webpack 服务器,可以直接使用 npm run dev 来开启服务器预览 Vue 生成静态页面。

2.2 Vue 前端页面概览

  前端的界面借助于饿了么开发的 element 框架,使用搭建 admin 后台,这里借助了 Github 上开源的 Vue-element-admin 进行简单的构建。

  首先我先去 Github 上将相关的仓库 clone 下来,然后通过 npm 模块管理器安装 Vue 相关的 JavaScript 模块。由于国内的网络原因,这里我采用了淘宝的镜像源来加快模块的下载速度。

  执行 npm install 命令安装模块可以读取当前目的 package.json 文件,自动安装项目的相关依赖。安装完成之后会在当前的目录下增加一个 node_modules 目录,当前目录里面就包含了启动项目所有的依赖项,通过执行 npm run dev 命令.启动前端页面。

图2.1 前端登录页面

  后续点击登录即可进入到框架提供的后台管理页面,登录进去之后的页面如下:

图2.2 模型列表页面

  后台系统包含了用户中心可以查看用户注册的信息,以及所有的模型列表还有模型的贴图和上传用户的名称。

  整个模型列表页面包含了数据库的增删改查所有的操作,其中左上角有搜索栏可以进行模型搜索,也可以点击添加按钮添加新的模型项。

  模型列表的右侧有每一个模型记录的修改按钮和删除按钮。

  删除按钮通过 element-ui 的 el-popconfirm 进行了防误删处理,给用户一个提醒。

图2.3 防止误删除警告

  修改按钮点击可以打开外部链接进入到 WebGL开发的编辑器进行模型文件的修改。

2.3 Vue 代码开发

  成功启动项目之后,我们可以去到 src\router 文件夹去配置页面的路由, Vue-element-admin 的路由和侧边栏是绑定到一起的,因此只需要配置路由就可以完成后台系统的侧边栏配置。

  路由配置分别指向对应的组件页面就可以实现点击侧边栏进行相应页面的跳转,使用Vue.js 的前端框架比起过去的 JQuery 操作会更加方便有效。

图2.4 路由配置

  配置好路由之后就就可以去到相应的组件进行页面编写了,这里配置的 Component路径 \@ 表示 src 的目录,这个配置可以在 jsconfig.json 文件中找到。

  用户中心的代码文件再 profile 文件夹里面,这里使用了三个组件来组成分别修改用户的头像信息以及用户个人信息和修改密码。

图2.5 用户中心代码

  在 js 的路径部分,这里使用了 Vuex 进行全局的状态管理,通过 axios 来发送响应的 http 请求访问后端程序,实现从数据库中获取数据。

  模型列表的部分就比较复杂一点,这里通过 el-table 组件实现数据的呈现,从后端获取了数据之后,通过前端 js 的filter 对数据进行过滤和展示。

  点击修改按钮执行 js 命令打开 WebGL 编辑器外链接,点击删除按钮则直接删除当前列表中的数据。

图2.6 模型列表代码

  目前的开发阶段还没有搭建起后端数据,这里可以使用 Mock.js 来模拟后端数据返回的效果,从而测试我们网站的接口功能是否运行正确。

图2.7 Mock 模拟接口返回的数据

  下面就可以在 Vue 里面通过 axios 库来进行 http 请求访问模拟的数据端口获取模拟数据返回到前端页面当中。

图2.8 axios 访问请求后端接口

  其中request脚本封装了 axios 库的请求操作,让这里的代码更加清晰。

3.WebGL 编辑器开发

3.1 Three.js 三维基础

  Three.js 极大的简化了 WebGL 的操作,不再需要手动去处理 GL 的缓存,也不需要调用 compileShader 等一系列 WebGL 内置的API ,这些操作 Three.js 已经封装好了。使用 Three.js 搭建三维页面只需有三件套接口,即 场景 摄像机 渲染器 三样东西。

  有了这三样东西的确就可以搭建出一个三维场景,但是我们依然什么都看不到,还需要搭建出一个几何体来进行观察, Three.js 提供了一些创建简单几何体的 API ,可以通过BoxGeometry 创建几何体,然后赋予材质 MeshBasicMaterial ,最后通过 mesh 将所有的数据整合到一起,并且将 mesh 添加到场景中,就可以通过渲染看到场景中的几何体了。另外由于 WebGL 是图形化的处理,因此也需要类似游戏一样不断地去刷新页面来实现页面更新的交互,代码处理需要通过 js 的内置命令 requestAnimationFrame 的递归来实现自我调用的效果,从而实现帧刷新。

  下面就是搭建一个简单的 Three.js 场景的代码。

图3.1  简单三维场景搭建

3.2 Three.js 编辑器开发

  由于 Three.js 是基于 es5 的标准下开发的,这是一个历史问题了,因此这里没有使用前端的框架而是使用 JQuery 脚本来处理浏览器的 DOM。

  这里我们借助 Three.js 内置的 ui.three.js 脚本所提供的简单 UI 来讲来进行不同界面的编写。

  通过 Editor 脚本将所有的 UI 以及 Three.js 的场景全部整合到一起。其中利用 signal 脚本给编辑器创建了一个观察者模式,从而实现各种不同函数的注册方便后续进行相应的回调。

  最后会在 Eidtor 脚本里面搭建出 Three.js 场景所需的三件套。

图3.2  Editor脚本搭建

  这样就可以创建出一个 Editor 的类,然后通过 Editor 类将相关的 UI 挂在到Editor 上面。

  这里通过 MenuBar 来实现上方的菜单栏挂载,这里添加了编辑菜单,文件菜单,帮助菜单等菜单。

图3.3  Menu菜单处理

  另外还需要 Viewport 脚本处理摄像机控制,否则显示的页面里摄像机是无法动弹的,因此这里需要 EditorControl 来实现摄像机的控制器,通过raycaster通过发射射线来获取视窗里面点击的物体。

图3.4  射线获取点击

  最后获取到点击的物体之后,通过 Three.js 内置的 TransformControl 来显示控制轴从而实现控制器位置的更改。

图3.5  TransformControl 相关处理

  写完上述的脚本之后可以在 index.html 里面调用这里相关的类的来启动编辑器页面了。

图3.6  编辑器启动代码

  实现上面的脚本之后就可以在浏览器启动看到我们简单编辑器页面了。

图3.7  简单的编辑器页面

  后续就是进一步完善编辑器的功能,给编辑器添加编辑面板侧边栏和下方工具架。

  编辑面板需要集成大纲类表和物体的位移编辑以及材质编辑的功能,这里也运用了类似于菜单的集成方式,通过一个主要 SideBar 脚本将其他的组件集成到一起。

  其中会在界面中生成所有物体可能出现的属性,然后通过字典判断物体是否存在相关属性从而实现对数据的显示和隐藏。

图3.9  属性显示过滤

  物体的材质属性显示运用了同样的原理,读取物体的材质是否存在相关属性,存在属性才显示,从而实现编辑面板属性的动态更新。

  相关的属性更新则是通过命令模式,通过 Editor 注册相关的命令,然后在这里显示的组件发生更新的时候触发更新命令实现全部更新的统一。

  大纲列表的显示则是其实也很简单,通过递归的方式遍历场景中所有的物体,然后根据遍历到的层级添加响应的侧边宽度,实现一种属性结构的显示,这里使用了闭包的方式进行场景物体的遍历。

图3.10  简单的编辑器页面

  最后则是通过浏览器的 addEventListener 来实现鼠标的拖拽事件从而改变物体相应的层级,并且添加响应的信号槽来触发相应的注册事件。

  接下来就是底下的工具架创建了,这里要添加上位移旋转缩放的切换功能,还要有移动吸附的相关功能。

  只需要添加点击按钮提供的功能,然后根据 TransformControl 里提前设置好的信号槽进行属性设置就可以实现点击按钮切换控制轴的效果。

图3.11  工具架的控制轴设置

  至于工具架上的位置吸附功能也是通过信号槽事件进行触发,这里还添加多了以个场景信息的显示控制,场景信息通过遍历所有的场景获取出场景中包含的几何体个数以及边数面数,这里还增加了点击更新选择的数据的效果,从而可以统计单个模型的带线面效果。

  这里添加了编辑器网格显示的可视化控制,网格则是通过 GridHelper 辅助显示工具显示出来的。

  最后将上面的面板集成到 index.html 里面就有了基本的编辑器效果。

图3.12  面板集成

  这里生成物体使用了 uuid 的方式进行记录,确保生成的物体有唯一辨识码。可以快速获取物体而不会产生混淆。

  不过这里的面板显示会极大减少模型显示的空间,因此这里我在有下角添加了一个主菜单按钮,可以快速方便地隐藏掉编辑器的面板显示。

图3.13  右侧菜单

  这个菜单动画通过 JQuery 插件实现,面板的隐藏则是直接获取面板的 id 标记进行toggle动画隐藏,另外这里还添加了正侧顶视图的正交视图效果,通过修改 Three.js原生的 EditorControl 实现透视摄像机和正交摄像机两种不同视角的切换。

图3.13  判断当前摄像机的类型从而实现不同的操作方式

  另外默认情况下,编辑器是没有默认灯光的,因此添加了模型之后就是黑漆漆的显示,因此我参考了 Maya 一类的软件添加了默认的摄像机灯光,光照方向沿着摄像机方向照射过去,确保即便没有灯光也可以观察到模型的基础显示效果。

4. Go后端服务开发

4.1 Golang 语言概览

  Go语言是谷歌推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂度。

  Go具有现代程序语言的特色,包括垃圾回收、内存管理等功能。而且Go的运行速度非常快,几乎和 C 或 C++ 程序媲美,能够快速迭代开发。

  Go专门为构建服务器所设计的,因此他的并发性能非常良好,而且解决了多核心处理器调用的难题,让Go能够充分发挥现代计算机硬件的性能。

  相较于边语言,Golang的语言特性让其短短十几年内快速发展,越来越多大公司的后端服务都开始转向 Go 语言进行构建,大名鼎鼎的 Docker 项目就是用 Go 开发的。

4.2 Iris 框架介绍

  Iris 是Go语言中用来开发 Web应用的框架,他可以在不同的机器上高效率运行,而且API非常简单功能却非常强大,最重要的是支持后端的 MVC 框架,更加方便企业级项目的管理。

  目前Iris框架是后端领域中性能最强的框架之一。

图4.1  Iris框架性能对比

  Go 服务器采用 Iris 框架,基于 Xorm 进行进行 mysql 数据库绑定。服务器后台使用腾讯云购买的服务器,使用宝塔面板搭建数据库进行管理。

4.3 服务器环境配置

  首先去到腾讯云的服务器上安装 Linux 操作系统的镜像,然后通过 ssh 配置登录到服务器的命令行面板里面,执行宝塔面板的安装命令即可全自动安装宝塔面板,然后通过宝塔面板可以图形化配置服务器。

图4.2 宝塔面板的安装命令

  yum模块是 Centos 自带的系统包管理器,可以获取一些别人整理好的模块安装到当前系统里面。

  安装完成之后就可以顺利通过宝塔面板的提示登录到面板系统当中。

图4.3 宝塔面板的安装完成提示

  顺利登录进入宝塔界面之后可以根据提示快速配置服务器需要用到的环境。比如Mysql数据库以及数据库管理工具 phpMyAdmin 来图形化管理 Mysql数据库。

图4.4 快速配置服务器环境

  可以去到宝塔面板的数据库页面去新建一个新的数据库。

图4.5 新建数据库

  新建数据库可以配置数据库的登录账号和密码,自动分配数据库访问权限,也可以设置数据库只供本机 IP 进行访问,防止被恶意利用。

图4.6 phpMyAdmin界面

  完成数据库搭建之后就可以登录到 phpMyAdmin 界面里管理 MySql 数据库里的表和数据了。

4.4 Go代码编写

  编写Go需要先安装 Go编译器,可以去中文官网下载Go编译器的安装包进行安装。

  安装完成之后,就可以通过命令行调用 go 命令来执行 Go 语言的代码。

图4.7 简单的Go代码运行

  下面就可以通过 Go 来安装搭建服务器所需要依赖的代码库了,通过 go get 命令可以直接将 github 上的源码库下载 GOPATH 环境变量路径所指向的 src 目录里面,get下来的模块就可以全局 import 导入来使用了。

图4.8 代码目录结构

  Go的后端代码基于 MVC 框架加 Service 服务实现,由于后端没有界面,因此这里的View指代的是路由地址,前端界面通过 http 请求访问不同的路由地址,Go会根据请求去调用对应路由的 Model 和 Controller ,而 Service 则将数据库的操作从 Controller 分离出来,方便不同 Controller 之间的相互调用。

  首先需要去 config.json 文件配置服务器监听的地址以及数据库访问的一些信息。

图4.9 配置文件

  然后通过读取 json 文件配置来连接到线上的数据库。

图4.10 Go 解析json数据

  读取的数据可以用来初始化 Iris 框架的挂载,并且配置好 xorm 模块的数据绑定实现数据库的自动录入更新。

  下面可以创建Model文件来描述数据库数据存储的格式,通过 xorm 提供的sync2方法可以自动在数据库创建出相应的表格。

图4.11 配置Model数据绑定

  通过StaticWeb 命令配置服务器的静态资源目录,这样只要启动 Go 服务,就可以通过本地域名加端口来访问到这些目录所配置的静态资源了。

图4.12 配置静态资源路径

  下面就是 Main 函数里面最重要的 mvcHandle 函数的处理了,这里定义了路由的设置并且通过路由调用相关的 Model 和 Controller ,不同的 Controller 调用相应的 service 来实现数据库的读写操作,这样分层的好处在于各个模块不会耦合到一起,方便代码管理和拆分,也方便来团队协作开发。

图4.13 路由挂载

  接下来就可以去到 Controller 来控制具体的请求了。

  Iris框架可以根据函数的命名来匹配响应的请求以及请求地址,比如我这里有PostLogin 函数,Iris 会自动转换为 /api/users/login 地址下的 Post 请求所执行的函数,这样就让配置更加简洁清晰。

图4.14 访问请求处理

  通过上面的配置就实现了管理员登录接口的功能,GetByAdminNameAndPassword函数会调用 service 的数据库查询方法来查询管理员账号是否存在。

图4.15 数据库查询

  如果管理员存在并且密码和存储的密码一致,才会返回存在的数据,从而实现用户的登录功能。

  下面还需要通过接口测试工具 postman 模拟 http 请求来测试接口编写是否存在问题。

  可以先将Go服务器运行起来,我的默认配置是监听到本地的 8080 端口。

图4.16 运行Go服务

  这样Go服务器就已经运行起来了,这时候就可以通过浏览器访问 localhost:8080 访问到之前静态挂载的页面了,下面就可以通过MVC配置的路由地址通过 postman 软件来模拟浏览器发送的http请求,从而可以测试接口返回的数据是否符合我们的预期。

  Postman的使用非常简单,只需要输入访问地址,然后选择请求的类型,然后将请求相关的数据配置好就可以点击 Send 发送请求了。

  下面的 Body 可以看到访问的端口所返回来的数据。

图4.17 Postman 测试端口

  端口返回的数据可以通过前端的 Vue 进行解析,从而在前端页面显示出相关的错误信息。

  最后前端端口全部配置完成通过测试之后,可以通过 npm run build 将 Vue 的界面听过 WebPack 打包精简成一个小型的静态页面,通过 Iris 静态挂在到服务器上,Vue发送请求就可以调用 Iris 来进行数据交互,我们的 WebGL 三维网站就初步搭建完成了。

5. Python Qt CefWidget 开发

5.1 基于PySide构建桌面程序

  通过上面的步骤,我们已经成功搭建起了一个运行的WebGL 网站,下面我需要将这个网站嵌入到 DCC 软件中,比如 Maya 三维软件,从而搭建出一个简易的三维资产库来管理这些生产工具所创建出来的三维资源。

  当前主流的 DCC 软件都是由 Qt 框架搭建,Qt框架是一门跨平台的 C++ 图形界面开发的框架,可以实现 Python 绑定从而大大简化了界面开发的难度,而主流的Python绑定库大都使用了Qt 官方提供的 PySide 库。

  使用 PySide 构建一个桌面应用程序非常简单,首先安装 Python ,然后通过 pip 命令安装 PySide 库,这样就可以在 Python 代码里面 import PySide 模块。

图5.1 简易的 PySide 界面搭建

5.2 Cef浏览器嵌入框架

  有了图形化界面的概念之后,下面需要将浏览器嵌入到 PySide 的界面当中,尽管PySide已经提供了一部分浏览器功能,可以访问大部分的网上页面,但是对 WebGL的支持依然不友好。

  因此这里我需要另辟蹊径解决 Qt 的浏览器嵌入问题,经过我不懈的努力我找到了一个很不错的解决方案,通过 cefpython 嵌入到 PySide 界面中。

  CEF 全称是 Chromium Embedded Framework,中文名称Chromium嵌入式框架,可以将谷歌浏览器的内核 Chromium 嵌入到任意界面当中,实现JavaScript 代码的编译与运行。

  cefpython 则是 CEF 框架的 Python 绑定,通过 CEF 框架的嵌入特性,只需要提供窗口的id就可以将浏览器窗口嵌入进去,操作起来很简单。

  由于 CEF 框架是由 C++ 模块编写的,python 绑定会涉及到 Cython 编译的 pyd 文件,这种情况下是无法在诸如 Maya 之类的 DCC 平台进行导入的。

  因此这里我采用了 socket 套接字编程将CEF模块通过 pyinstaller 封装成一个可执行的 exe 文件进行外部启动,通过 socket 来进行进程见得数据通信,从而在 Maya 上仍然可以控制到 CefPython 启动的浏览器模块。

5.3 CefWidget Python代码编写

  为了兼容 Qt 框架不同 Python 绑定,这里我使用了 Github 上开源的 Qt.py
  来导入相关的Python Qt 模块。

  这里的代码结构包含两个脚本,一个是用来提供浏览器嵌入窗口的 Qt
  组件,组件上提供了连接 socket
  的方法来操控浏览器,而另一个脚本则是创建一个远程端口来运行 CEF 浏览器。

图5.2 remote 创建一个socket 套接字

  通过socket绑定到端口上,后续通过 while
  循环获取传递到端口中的字符串数据,根据传递进来的字符串数据就可以解析出需要执行的事件,从而实现
  CEF窗口的控制。

图5.3 通过 while 死循环不断监听端口数据

  浏览器窗口也需要类似于Qt的界面一样不断执行来响应窗口的事件,cefpython提供了cef.MessageLoopWork()的方法来调用窗口的事件序列,这样只要将这个方法放到死循环里面执行就可以保持浏览器的持续响应,同时也不会因为端口监听互相冲突,这样就可以通过
  socket.accpet()
  来获取到端口的客户端,再从客户端获取传递进来的数据,根据传递的数据调用不同的方法,诸如创建一个新的浏览器,以及加载特定链接等等功能。

图5.4 函数功能判断

  这里通过 terminate 关键字来打断循环,从而正确结束掉端口和运行中的 CEF
  浏览器,否则死循环会一直占用端口,导致下次端口监听导致端口已经被占用报错的情况。

  除了一些特殊的关键字信息处理之外,大部分数据处理都传递到 self.callback_dict
  中进行通用的函数处理,大大简化了代码量。

  搭建好了 cef
  后台socket的脚本之后,Qt组件的脚本可以添加一个装饰器来自动开启和关闭这个
  socket。

图5.5 scoket初始化和关闭

  通过 python 的 subprocess
  模块来外部运行脚本,初始化socket,然后这里可以通过构建客户端 socket 来发送
  terminate 关键字来结束所有的socket。

  CefBrowser 组件继承与 QWidget ,通过 QWidget 提供的 winId
  方法可以获取到当前组件的唯一winId,随后就可以通过这个 id
  将浏览器窗口嵌入到这个组件的界面当中。

图5.6 CefBrowser获取窗口的id

  通过embed 函数将窗口嵌入到当前组件中。

图5.7 CefBrowser 为当前组件生成浏览器并嵌入

  这里通过python 的 uuid
  模块获取当前组件的唯一辨识符,并且传递到生成的浏览器当中,这样发送数据到浏览器
  socket 的时候就可以通过唯一辨识符知道要对哪一个浏览器窗口进行处理。

图5.8 Connect函数封装了端口访问的代码

  通过Connect 函数封装,方便数据发送。

图5.9 调用不同的函数向端口发送不同的数据

  通过发送字符串数据,就可以发送到浏览器运行的端口程序里,从而让
  CefBrowser嵌入的浏览器响应事件,封装成浏览的处理函数之后也支持 Qt
  内置的点击按钮触发事件功能。

图5.10 浏览器嵌入测试

  后面根据 cefpython 官方提供的 pyinstaller 打包方案,将 remote.py
  打包成一个可执行文件,这样脚本就不再需要依赖 python 进行运行,也不会因为 maya
  等软件的python.exe是特殊编译的版本导致不兼容运行出错。

  Pyinstaller 是 python 程序打包成 exe
  可执行文件的方案,这个包支持跨平台程序打包,使用起来非常友好,cefpython 需要配置
  pyinstaller.spec
  来定义需要进行打包的程序以及路径,具体操作可以参照官方的打包文件案例。

  我这里在官方的基础加上了一些改良,比如打包成功之后自动打开打包的文件,自动读取当前运行脚本目录下的
  remote.py 进行打包等等。

图5.11 使用 pyinstaller 打包程序

  打包程序需要花费一些时间,打包完成之后会在目录中生成build文件夹,其中的cefapp.exe可执行文件执行的效果就和
  remote.py 一样,但是不再需要依赖于当前执行的python就可以在 Maya 等 DCC
  软件中启动当前程序。

图5.12 在Maya中启动 CefBrowser

  同样的方法,我们可以将之前做好的WebGL网站运行起来,就可以在网站上访问到WebGL编辑器并且查看上传的三维资产了。

图5.13 在Maya中启动 WebGL 三维模型展示网站

图5.14 在Houdini中启动 WebGL 三维模型展示网站

总结

  前端使用 Vue-element-admin 其实并不太好。
  一方面是我对这个后台前端框架不熟悉,使用起来磕磕绊绊的,最主要的是默认提供的功能过于冗杂了。
  其实我的网站非常简单的,很多代码模块都可以删除。

  后面用 Go 做后端测试,遇到了很多问题。比如我本地测试遇到了跨域问题。
  网上搜索了一下 Vue 可以借助 node.js 进行请求转发,毕竟跨域保护是在浏览器生效的, node.js 没有跨域强求的限制。
  然而某些情况还是会出问题。
  后面在 Response Header 上加上跨域的信息之后也不行。
  于是神奇的情况出现了,使用 postman 进行请求模拟没问题,但是当我尝试复制 postman 生成的代码到浏览器执行会出现 Network Error 访问不到的情况。
  后来是关了请求转发才可以,真的是日了狗了。


  然后就是 sql 语句编写,Go 的 Iris 框架通过 MVC + Service 来操作 sql
  Iris 框架也是个大坑,网上的资料比较少,出问题查询起来有点麻烦,好在 Stack Overflow 依然很实用。
  sql 语句我写得少,其实用得还不是很顺手,后续打算弄个 sqlite 练习熟悉一下 sql 语句。

  Go 语言完全没有练习基础就对照着教程提供的 Iris 框架代码进行开发,其实个人感觉不太好,有点不知其所以然的感觉。
  而且遇到问题需要不停的查找,可能还是初期的不适应有关系。
  总之是 Go 的使用经验还不足。


  关于 Three.js 编辑器改良上,其实无非就是用了 ES5 JQuery 插件和 Bootstrap 界面开发的方法改良的。
  不过是 ES5 的东西都是几年前过时的标准了,初学前端还是学了这一套,bootstrap 有可视化编程,感觉依然是很香的。
  整个编辑器主要还是从 Three.js 官方编辑器上改的,用了官方提供的 dark.css 样式,所以工作量不大。
  主要添加了 四视图摄像机切换 , 这个过程设计到 正交摄像机和透视摄像机的切换, 操作过程嵌入到了 EditorControl 里面了。
  另外就是添加了根据镜头方向照射的默认灯光,类似Maya,不至于让场景纯黑。


  CefWidget 嵌入 DCC 其实都是之前帮师兄搞 宙斯 搞的东西了。
  具体可以参照我之前的博客文章,不过 WebGL 的效率其实不高,而且如果不从浏览器底层剥离 WebGL 的相关程序,整个浏览器过于臃肿了。
  师兄推荐用 USDview ,的确是值得考虑的。


  一转眼大学就毕业了,时间真是一把杀猪刀呐~