Mesh绘制交互网格

发表于2018-11-22
评论0 8.9k浏览
上一篇给大家分享了如何使用Mesh网格做一个快速切割的效果,其实在游戏中还有其他效果存在,就拿下面这篇要和大家分享的使用Mesh绘制交互网格的效果。

最终效果

思路

使用B曲线平滑连接和排序网格
销毁网格
彩虹滚动使用shader实现

连接的网格


先让我们看看生成的线条在编辑器中的样子,看起来很夸张,为了让我们后期能对他进行裁剪和逐步消失功能,我生成了一系列小网格搭配BOX碰撞。

因为网格是我们自己绘制的,我们知道每个顶点的序号,所以我们只需要根据鼠标方向生成下个网格,旧网格的结束顶点的坐标改成新网格起始顶点的坐标,就可以实现网格连接。
        public void LinkNext(Vector3[] pos, float lerp = 1f)
        {
            for (int i = 0; i < pos.Length; i++)
            {
                //将坐标转换为本网格的局部坐标
                pos[i] = transform.InverseTransformPoint(pos[i]);
            }
            for (int i = Verts.Length - 1, j = pos.Length - 1; j >= 0; i--, j--)
            {
                //按顺序赋值给本网格的末尾顶点
                Verts[i] = Vector3.Lerp(Verts[i], pos[j], lerp);
                Normals[i] = new Vector3(Verts[i].x, Verts[i].y, 0);
            }
            MeshFile.mesh.vertices = Verts;
            MeshFile.mesh.normals = Normals;
        }

平滑网格

但是这样连接的鼠标操作时,都会出现类似上面蓝色网格的形状,网格的棱角和变形是难以避免的。

纵使你增加网格段数,然后使用四元数或者旋转矩阵来弯曲这个网格,依然会出现其他问题。

问题的根本在于鼠标的轨迹,我们扑捉的鼠标轨迹不是连续的平滑的。

所以是用B曲线来平滑鼠标路径的顶点。
        public static Vector3 CatmullRom(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float i)
        {
            return 0.5f * ((2 * p1) + (-p0 + p2) * i + (2 * p0 - 5 * p1 + 4 * p2 - p3) * i * i + (-p0 + 3 * p1 - 3 * p2 + p3) * i * i * i);
        }

网格的消失和切割


我们希望我们的网格是逐步消失的。

逐步消失我们可以使用刚体的缩放变换,根据模型的尺寸进行顶点偏移,
        public void ScaleMesh(float inter, Axis axis, bool reverse = false)
        {
            Vector3[] _verts = new Vector3[Verts.Length];
            Vector2[] _uvs = new Vector2[Uvs.Length];
            Vector3 _v0;
            Vector2 _uv;
            if (reverse)
            {
                _v0 = MeshFile.mesh.bounds.min;
                _uv = minUV;
            }
            else
            {
                _v0 = MeshFile.mesh.bounds.max;
                _uv = maxUV;
            }
            for (int i = 0; i < Verts.Length; i++)
            {
                switch (axis)
                {
                    case Axis.X:
                        _verts[i] = new Vector3(Mathf.Lerp(Verts[i].x, _v0.x, inter), Verts[i].y, Verts[i].z);
                        _uvs[i] = Uvs[i];
                        break;
                    case Axis.Y:
                        _verts[i] = new Vector3(Verts[i].x, Mathf.Lerp(Verts[i].y, _v0.y, inter), Verts[i].z);
                        _uvs[i] = Uvs[i];
                        break;
                    case Axis.Z:
                        _verts[i] = new Vector3(Verts[i].x, Verts[i].y, Mathf.Lerp(Verts[i].z, _v0.z, inter));
                        _uvs[i] = new Vector2(Uvs[i].x, Mathf.Lerp(Uvs[i].y, _uv.y, inter));
                        break;
                    case Axis.ALL:
                        _verts[i] = Vector3.Lerp(Verts[i], _v0, inter);
                        _uvs[i] = Vector2.Lerp(Uvs[i], _uv, inter);
                        break;
                }
                MeshFile.mesh.vertices = _verts;
                MeshFile.mesh.uv = _uvs;
            }
        } 
上面的代码让我们在模型保持UV不变的情况下在一个轴向上进行缩放。

因为我们的线是一列网格组成的,当缩放为0时,销毁自身,告诉下个网格继续缩放即可。
当被切割时,切到哪个box Collider,通知那个模型的前后网格开始缩放销毁操作即可。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

标签: