【Unity】MeshEditor.Effects.Vortex 网格编辑器特效篇之碎化特效

更新日期:2020年5月13日。
Github源码:[点我获取源码]

索引

  • Fragmentization
    • 使用
    • 参数
    • 原理及算法
    • 图像展示

Fragmentization

设置一个碎化起始点,使得网格从该点开始逐渐破碎。

使用

Hierarchy界面选中一个带网格渲染组件(MeshRenderer或SkinnedMeshRenderer)的物体,在物体名字上单击右键,选择创建MeshEditor > Effects > Fragmentization

调用Play播放特效,Pause暂停特效,UnPause恢复特效,Stop停止特效。

参数

【Unity】MeshEditor.Effects.Vortex 网格编辑器特效篇之碎化特效_第1张图片
Fragmentization参数面板:
1.Play On Start:是否在Start时自动播放特效。
2.Frag Point:碎化起点。
3.Frag Health:碎片生命力。
4.Frag Speed:碎片分离速度。
5.Frag Rate:碎化速率。
6.Fragment Type:碎片行为控制者。

原理及算法

碎化算法主要分为以下四个阶段:
1.计算离碎化起点最近的三角面,保存为起点三角面;
2.从起点三角面开始,计算碎化顺序;
3.根据碎化顺序逐渐分离三角面;
4.如果发现网格还有剩下的三角面,重新执行1。

计算起点三角面:计算起点三角面很简单,遍历所有三角面比一下距离就可以了,这点可以丢到子线程里面去,不过开销并不大,暂时没这么做。

        //获取第一个三角面,碎化起点
        private Triangle GetFirstTriangle(MeshData meshData)
        {
            Vector3 fragPoint = transform.worldToLocalMatrix.MultiplyPoint3x4(FragPoint);
            Triangle triangle = meshData.Triangles[0];
            float distance = Vector3.Distance(fragPoint, meshData.Triangles[0].Center);
            for (int i = 1; i < meshData.Triangles.Count; i++)
            {
                float dis = Vector3.Distance(fragPoint, meshData.Triangles[i].Center);
                if (dis < distance)
                {
                    triangle = meshData.Triangles[i];
                    distance = dis;
                }
            }
            return triangle;
        }

计算碎化顺序:这里的算法稍微有点复杂,采用相邻三角面排序算法,一个开启列表、准备列表、关闭列表(HashSet)同时参与计算,思路:查询准备列表,只要准备列表中存在三角面,就将该三角面纳入开启列表,开启列表中的三角面会被立即加入关闭列表(完成排序),然后开启列表中的三角面的邻居会被纳入准备列表。目标是根据网格中三角面的相邻关系,生成一个列表。

        //获取三角面碎化顺序算法
        private void GetTrianglesOrder(Triangle first)
        {
            _trianglesOrder.Clear();
            _triangleOpen.Clear();
            _triangleReady.Clear();
            _triangleClose.Clear();

            //将第一个三角面加入准备列表
            _triangleReady.Add(first);

            //如果还有准备中的三角面
            while (_triangleReady.Count > 0)
            {
                //将准备中的三角面纳入开启列表
                _triangleOpen.UnionWith(_triangleReady);
                _triangleReady.Clear();

                //遍历开启列表,逐一关闭
                foreach (var item in _triangleOpen)
                {
                    CloseTriangle(item);
                }

                //遍历开启列表,逐一将其邻居纳入准备列表
                foreach (var item in _triangleOpen)
                {
                    ReadyNeighborTriangle(item);
                }

                _triangleOpen.Clear();
            }

            _triangleOpen.Clear();
            _triangleReady.Clear();
            _triangleClose.Clear();
        }

        //关闭三角面,三角面加入关闭列表
        private void CloseTriangle(Triangle triangle)
        {
            if (!_triangleClose.Contains(triangle))
            {
                _triangleClose.Add(triangle);
                _trianglesOrder.Add(triangle);
                triangle.BrokenLinkVertex();
            }
        }

        //准备相邻三角面,三角面加入准备列表
        private void ReadyNeighborTriangle(Triangle triangle)
        {
            foreach (var item in triangle.Vertex1.Triangles)
            {
                _triangleReady.Add(item);
            }
            foreach (var item in triangle.Vertex2.Triangles)
            {
                _triangleReady.Add(item);
            }
            foreach (var item in triangle.Vertex3.Triangles)
            {
                _triangleReady.Add(item);
            }
        }

分离三角面:这里会根据碎化顺序弹出排在第一位的三角面,并生成实体碎片(实体碎片对象池),直到排序列表中不存在三角面,然后再次确认网格是否还有三角面残留(某些模型由几部分网格组成,网格之间不相邻,只通过执行一次计算顺序算法并不能找到所有三角面)。

        //分离三角面
        private void Fragmentization(MeshData meshData)
        {
            if (_trianglesOrder.Count > 0)
            {
                Triangle triangle = _trianglesOrder[0];
                _trianglesOrder.RemoveAt(0);
                meshData.RemoveTriangle(triangle);
                GenerateFragment(triangle);
            }
            else
            {
                _timer = 0;

                if (meshData.Triangles.Count > 0)
                {
                    GetTrianglesOrder(GetFirstTriangle(meshData));
                }
                else
                {
                    Stop();
                }
            }
        }

图像展示


你可能感兴趣的:(MeshEditor,Unity,Unity,Editor,Develop)