云服务器 能用来做网站吗/关键词制作软件
更新日期:2020年5月13日。
Github源码:[点我获取源码]
索引
- Fragmentization
- 使用
- 参数
- 原理及算法
- 图像展示
Fragmentization
设置一个碎化起始点,使得网格从该点开始逐渐破碎。
使用
在Hierarchy界面选中一个带网格渲染组件(MeshRenderer或SkinnedMeshRenderer)的物体,在物体名字上单击右键,选择创建MeshEditor > Effects > Fragmentization。
调用Play播放特效,Pause暂停特效,UnPause恢复特效,Stop停止特效。
参数
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();}}}
图像展示