Dust3D是Jeremy HU 个人开发的一款3D建模软件,主要用于游戏模型的快速制作。虽然作者已经在某种程度上放弃了该项目,但其分享的Dust3D从起心到技术选择到最终实现的整个心路过程,很有借鉴意义。

1、起心动念

自2015年以来我就想写一个3D建模软件,那时我正在开发2.5D的MMORPG游戏。我在YouTube自学了一段时间的Blender软件,Blender其实相当不错,但是,这个过程中的工作量让我意识到,一个人不可能完成大量的模型、制作纹理、动画,然后在游戏中使用,因为只是建立一个简单的恐龙模型就花了我半天时间。

我看了很多关于如何快速制作游戏模型的教程,试图找出一个统一的方式,一个可重复的模式,可以在编程语言中简化。我总结了制作模型的最常见步骤:首先,为前视图、侧视图和后视图设置参考样张,其次,制作平面,然后细分为六边形,通过遵循参考仰仗挤压此六边形,调整面部大小,以不同角度微调,来回调整,最后获得基本模型。

2、最初的实验

看起来我可以写一个软件来自动完成这些步骤,输入参考样张,它输出一个模型。让我们实现这一点,我做了一个非常粗糙的测试程序,以识别图像中的每个视图,提取边界,根据边界挤压面孔,但它太小了,不能在游戏中使用。

3、来自Jimmy的新想法

有一天,我搜索了一些有关怪物生成的关键字,并找到了Jimmy Gunawan的博客, 我被他的文章震惊了,这就是我要找的,这就是答案,我非常兴奋,当读到博客上关于Blender的皮肤修改器背后的技术时,我发现了论文:B-Mesh: A Fast Modeling System for Base Meshes of 3D Articulated Shapes,这一刻我就知道,是时候将我最初的想法变成真实的产品了。

4、启动Dust3D项目

我启动了 Dust3D 项目, 并在reddit贴出了我的计划,虽然这是我还没有做很多事情。我这样做是因为,作为游戏行业的新手,我不想在一开始错过一些事情。感谢令人赞叹的reddit用户,我学到了很多新的软件名称和建模术语,如Meshmixer,CGAL,等等。

5、重新发明车轮

重新发明车轮很有趣,所以我没有严格遵循尽量使用已有库的建议,我想从头开始制作一个3D软件。我想逐点逐行绘制3D世界。这是 Dust3D 的第一个屏幕截图,使用原始 OpenGL,除了 OpenGL 环境,没有任何其他依赖:

很快,我发现调试绘图问题花了这么多时间,所以我小心谨慎地引入了GLU库,现在看起来是这样:

过了一段时间,我认为Qt非常容易使用,所以我小心地引入了Qt。然后实现了 Bmesh 算法:

Catmull-Clark 细分:

现在,是时候做一个更正式的用户界面了。

6、再次重造车轮

你可以看到,dust3d是从零依赖开始,然后不可避免地引入一些东西。如果继续这样下去,一切顺利。但有些事情发生了。由于没有复杂的UI,我使用Blender建立Bmesh球之间的关系,我发现Blender软件在Callada输出器中的一个bug,我试图自己修复它,所以我下载了Blender的源代码,修复并提交了一个补丁。在此过程中,我厌倦了折腾C++的不同版本的问题,因此我决定从 Dust3D 代码库中删除所有C++代码。

Qt是C++,因此Qt被删除。我试图找到一些替代的UI库,ImGui看起来很有前途,但因为它是C++写的,所以被放弃了。我又从零开始实现UI,这就是它的外观:

啊哈!

7、休整与重新思考

当我在澳大利亚启动Dust3D 项目时, 我使用的是工作和度假签证。有很多事情阻止了我继续开发这个项目,那段时间相当繁忙。这让我重新思考所做的决定。删除所有的依赖并不好,我正在做的是一个3D建模软件,而不是GUI库。我也开始考虑建模过程的一些细节。在Bmesh论文中,作者指出了存在的一些限制,即它不适合制做锐利的边缘。我们都知道,当我们为游戏做模型时,不可避免地会需要做出一些锋利的形状。

8、技术路线再调查

我利用YouTube上的视频教程梳理了几乎所有的建模软件,试图找出他们的实现机制。这些软件包括Houdini,它的以节点为基础的建模技术让我感到震惊。我想这就是我想要的, 这就是答案, 看起来很熟悉, 对吗?:-)

9、重新开始Dust3D

我创建了一个名为poc的新分支来验证概念。我没有完全实现基于节点的建模,二十尝试定义一个新的建模脚本语言,它可以很容易地嵌入到命令行中。当时,我构建了许多基本的mesh操作算法,如斜切计算、布尔计算等。

9、上手Rust

我不记得确切的原因,也许是项目名称?无论如何,我被Rust语言分心了。我试着用 Rust重写 所有基本mesh算法来练习语言技能。这就是meshlite库的来由。

10、完成Dust3D

现在,我对mesh有了更好的理解,并且知道如何生成我想要的mesh,无论它光滑还是锋利。完成mesh库后,我尝试再次构建UI。在rust世界中,没有那么多的UI框架可供选择。我做了一些调查,并尝试了许多GUI解决方案,如bgfx,我甚至修复了bgfx的一个微不足道的问题,并且合并进主分支。但最后,我仍然决定使用Qt。这一次,整个编码进度非常顺利, UI用Qt,算法用Rust,配合起来很爽,而且Rust从来没有在正常用例中崩溃,我的意思是说,Rust在建立像双向链表这样的数据结构时有一些固有的问题,所以我需要一些不安全的代码或基于索引的系统来支持多重链接数据,如mesh处理中著名的half-edge结构,因为基于索引的系统不受Rust语言的保护,有时,它会因一些逻辑错误崩溃。我发现Rust、C++11和Qt新的信号插槽用起来很顺手,我也高兴地引入了Carve和CGAL库来实现mesh union操作。

11、Dust3D现状

今天,我决定分享我的故事,我已经完成了第一阶段的Dust3D。它并不完美,但这是我多年前就设想的产品。这就是我想要的,这是我过去几年付出的答案。

12、Dust3D的未来

目前还没有实现没有自动拆解纹理,没有自动刚性处理,没有自动动画生成。还有很长的路要走,我很期待。谢谢你的阅读。

PS:自动拆解纹理和自动刚性已经完成,自动动画正在开发中。(2018年5月30日)


原文链接:Write a 3D modeling software from scratch

BimAnt翻译整理,转载请标明出处