emmm,一不小心就半年没更了,最近翻到了本科毕设,挺有感触的,就拿出来写写。
Tip0: 代码写的时间过长,本文很少很少的细节地方与代码对不上,见谅。
Tip1: 要是拿了我的代码,留下个评论,点个赞可好。
程序源代码链接:https://pan.baidu.com/s/1hxCGDYFz0ubAEhPCj_3xuA 提取码:zv9o
编译环境:Qt5.9.4
编译器:Desktop Qt5.9.4 MSVC2017 64bit
IDE:QtCreator
显卡:Nvida
一. 程序简介
可对常见的单子叶类盆栽植物,如吊兰,君子兰等进行三维建模,利用手绘系统简单对单支枝叶的曲线造型做近似的模拟。同时建立简单的天气系统,创造盆栽在刮风,下雨天气下的形态变化动画。
二. 模块分解
2.1 渲染
渲染模块使用之前教程提供的技术,都是很基础的技术:
- Blinn- Phong 光照模型
- 法线贴图 Normal Mapping
- 阴影映射 shadow Mapping (使用GLSL 原生函数)
2.2 枝叶建模
使用在矩形网格上附加透明纹理的方式生成枝叶,如图3所示,通过依次弯曲小矩形的形式可以构造枝叶的弯曲造型。
吊兰所用透明纹理与法线贴图如下所示,图4(c)为应用法线贴图之后的效果。
2.3 花盆建模
用之前教程提过的,导入一个obj花盆模型
2.4 手绘系统
枝叶的弯曲主要由网格的弯曲实现,利用矩阵与网格坐标相乘,可以在局部坐标系种改变顶点的位置。如图6,使用矩阵Model0与v0,v1相乘,改变两个顶点位置。可以简单定义Model0是绕x轴正向旋转5度的旋转矩阵,则相乘后v0与v1两顶点的空间坐标同样绕x轴正向旋转5度。为保证网格弯曲的平滑性,Model1与Model2等其余旋转矩阵可由上一个矩阵迭代生成。如在Model0矩阵的基础上,再绕x轴旋转5度,生成Model1矩阵。
手绘系统基于此思想,通过绘出的轮廓线条,计算所需迭代旋转矩阵数组中所有矩阵的旋转角度。为生成的枝叶弯曲的更加平滑,使用六次贝塞尔曲线对手绘线条进行曲线拟合,贝塞尔曲线控制点从手绘的线条种按点的密集程度进行筛选。如图7,黑色为手绘线条,红色为六次贝塞尔曲线控制点,蓝色为拟合后的曲线。将蓝色曲线均分为30个点,通过这些点计算旋转矩阵所需的角度,使用相邻两点在x与y坐标上的差值计算角的大小,,则为一个旋转角度,图7 (b)为应用旋转矩阵之后的弯曲网格造型。
简单绘制两线条,生成枝叶模型如下图所示。
Tip2: 这里在应用法线贴图时有一个错误,因为法线贴图里的法线针对的是平面不弯曲网格。这里我将网格弯曲后,原则上应对法线贴图的相应部分做同样的弯曲,我当初试了几次,应该算错了,一直没改。
2.5 其余功能
2.5.1 均匀分配枝叶
我每使用鼠标左键,以根部为起始方向,向左或向右绘出一条线条,在场景的YOZ平面,会进行相同方向的建模。如图9(b)所示。在绘出所有枝叶后,点击“移动”按钮,会将枝叶平均分配到花盆的四周,原理很简单,用360度除以枝叶的数量,得到枝叶的平均旋转角度,在此基础上,增加一些随机角度,则得到每枝枝叶的最终旋转角度。
2.5.2 增添枝叶
如果要设计一盆有几百枝枝叶的盆栽,将其全画出来,是一件很愚蠢的事,手动狗头。
如图10,简单画6个线条,设置“增补数量“为24,点击“计算”,则枝叶数量会扩充至24枝。原理是记录手绘线条的每组贝塞尔控制点,在这些控制点的坐标参数上增添微小随机量,得到一组新的控制点,生成新的贝塞尔曲线,从而得到一条新的枝叶模型。
2.6 天气系统
Tip3: 天气系统,当初写这个就是个噱头,忽悠老师的,没用物理参数,较真的哥们可以跳过。
天气系统分为两个,风动与下雨。下雨很简单,粒子系统做雨滴就完事了,没有参考价值。
风动是在做“平均分配枝叶位置”那得到的灵感,在移动的基础上,再增加一个绕x轴旋转的角度,将这个角度做成连续的,则动画就做出来了。这里我用组成贝塞尔曲线的30个绿色小点,点点之间在y值之上的差值,作为变换角度的参考。制作30个角度,作为动画演示之用。