一个网格合并(weld)小工具
在日常开发中会有需求合并多个Mesh网格,并且它们重合处的顶点也要合并,而并非合并成两个subMesh。
而近期刚好在学习Geomipmap的细分,需要把多个mesh块进行合并,于是写了这个脚本
(简单的情况下用Mesh.CombineMeshes也可以)。
见下图,多对象合并前后对比:
使用时传入多个MeshFilter,会返回对应Mesh,但是没做UV、顶点色这些,需要自己扩展:
namespace Hont
{
using System.Collections;
using System.Collections.Generic;
using UnityEngine; public static class MeshCombinerUtil
{
public static Mesh Combine(MeshFilter[] meshFilterArary, float weldDistance = 0.01f)
{
const int MESH_VERT_GAP = 10_0000; Dictionary<int, int> newTrianglesDict = new Dictionary<int, int>();
List<int> newTrianglesList = new List<int>();
List<Vector3> newVerticesList = new List<Vector3>();
List<KeyValuePair<Vector3, int>> meshSlotList = new List<KeyValuePair<Vector3, int>>(); int counter = 0;
for (int i = 0; i < meshFilterArary.Length; i++)
{
MeshFilter meshFilter = meshFilterArary[i];
Mesh mesh = meshFilter.sharedMesh; Vector3[] verticesArray = mesh.vertices;
int[] trianglesArray = mesh.triangles; for (int j = 0; j < trianglesArray.Length; j++)
{
int triangleIndex = trianglesArray[j];
int triangleIndexContainOffset = triangleIndex + i * MESH_VERT_GAP;
Vector3 vertex = verticesArray[triangleIndex];
vertex = meshFilter.transform.localToWorldMatrix.MultiplyPoint3x4(vertex); if (!newTrianglesDict.ContainsKey(triangleIndexContainOffset))
{
KeyValuePair<Vector3, int> slotInfo = new KeyValuePair<Vector3, int>(Vector3.zero, -1);
for (int k = 0; k < meshSlotList.Count; k++)
{
KeyValuePair<Vector3, int> meshSlot = meshSlotList[k]; if (Vector3.Distance(meshSlot.Key, vertex) <= weldDistance)
{
slotInfo = meshSlot;
break;
}
} //检索网格交错列表 if (slotInfo.Value > -1) //如果网格交错列表里有
{
newTrianglesDict.Add(triangleIndexContainOffset, slotInfo.Value);
}
else //如果网格交错列表里没有
{
meshSlotList.Add(new KeyValuePair<Vector3, int>(vertex, counter));
newTrianglesDict.Add(triangleIndexContainOffset, counter); ++counter;
newVerticesList.Add(vertex);
}
} //如果这个原始三角形索引字典里没有则初始化 newTrianglesList.Add(newTrianglesDict[triangleIndexContainOffset]);
}
} Mesh newMesh = new Mesh();
newMesh.SetVertices(newVerticesList);
newMesh.SetTriangles(newTrianglesList, 0); return newMesh;
}
}
}
2022/02/13补充,该脚本提供多个MeshFilter的合并,但并不会将硬边转软边,刚好这几天遇到一个需求要进行这一步操作。补充Mesh硬边转软边脚本,搭配使用:


public static Mesh HardEdgeCombine(Mesh mesh, float weldDistance = 0.01f)
{
int[] triangles = mesh.triangles;
Vector3[] vertices = mesh.vertices; List<int> newTriangleList = new List<int>(triangles.Length);
List<int> newVertexTriangleIndexList = new List<int>(vertices.Length);
List<Vector3> newVertexList = new List<Vector3>(vertices.Length); int trianglesCounter = 0;
for (int i = 0; i < triangles.Length; i++)
{
int triangleIndex = triangles[i];
Vector3 vertex = vertices[triangleIndex]; int dstTriangleIndex = 0; bool combineFlag = false;
for (int j = 0; j < newVertexList.Count; j++)
{
Vector3 compareVertex = newVertexList[j]; if (Vector3.Distance(vertex, compareVertex) <= weldDistance)
{
dstTriangleIndex = newVertexTriangleIndexList[j]; combineFlag = true;
break;
}
} if (!combineFlag)
{
dstTriangleIndex = trianglesCounter;
newTriangleList.Add(dstTriangleIndex);
newVertexList.Add(vertex);
newVertexTriangleIndexList.Add(dstTriangleIndex);
trianglesCounter++;
}
else
{
newTriangleList.Add(dstTriangleIndex);
}
} Mesh newMesh = new Mesh();
newMesh.SetVertices(newVertexList);
newMesh.SetTriangles(newTriangleList, 0); newMesh.RecalculateBounds();
newMesh.RecalculateNormals();
newMesh.RecalculateTangents(); return newMesh;
}
HardEdgeCombine
一个网格合并(weld)小工具的更多相关文章
- 开源一个Mac漂亮的小工具 PPRows for Mac, 在Mac上优雅的计算你写了多少行代码
开源一个Mac漂亮的小工具 PPRows for Mac, 在Mac上优雅的计算你写了多少行代码. 开源地址: https://github.com/jkpang/PPRows
- 用 C# 写一个 Redis 数据同步小工具
用 C# 写一个 Redis 数据同步小工具 Intro 为了实现 redis 的数据迁移而写的一个小工具,将一个实例中的 redis 数据同步到另外一个实例中.(原本打算找一个已有的工具去做,找了一 ...
- 自己动手写一个U盘拷贝小工具
这是五一期间,参照知乎上一篇的文章<十行代码--用python写一个USB病毒>写成的,最初只是单纯的想写成死循环,直到文件占满硬盘为止,第一个遇到的问题是,拷贝到硬盘之后,由于要无限次拷 ...
- (win环境)使用Electron打造一个桌面应用翻译小工具
初始化项目 npm init 修改package.json {"name": "trans","version": "1.0.0& ...
- 腾讯的一个移动端测试小工具GT
上周末参加了Ministar北京的测试聚会.腾讯的MIG专项测试组的组长给大家介绍了他们最近开发出来的手机测试工具GT. 下面是GT的官方说明: GT(随身调)是APP的随身调测平台,它是直接运行在手 ...
- 一个sql盲注小工具 (Golang版)
并发,二分法判断. 源码写的有点垃圾,有点乱,结果也存在一些缺失. 记录: sql:select distinct 中的distinct选项,这是只会获取你表中不重复数据,是表中,而不是你一次sql执 ...
- 好用的一个从SharePoint导出小工具
1. 输入 Site Url(Site Collection), 然后点"load"按钮 2.选择Web后,点选需导出的文档库,然后点"Next"按钮 ...
- 基于百度通用翻译API的一个翻译小工具
前几天写了一个简单的翻译小工具,是基于有道翻译的,不过那个翻译接口有访问限制,超过一定次数后会提示访问过于频繁,偶然发现百度翻译API如果月翻译字符少于200万是不收取费用的,所以就注册了一个百度开发 ...
- Python学习之旅:用Python制作一个打字训练小工具
一.写在前面 说道程序员,你会想到什么呢?有人认为程序员象征着高薪,有人认为程序员都是死肥宅,还有人想到的则是996和 ICU. 别人眼中的程序员:飞快的敲击键盘.酷炫的切换屏幕.各种看不懂的字符代码 ...
- ContentProvider域名替换小工具
开发项目域名想怎么换就怎么换,就是这么任性! 这是一个很有意思的小工具! 这是一个方便开发人员和测试人员的小工具!! 吐槽: 一直在做Android开发,一直总有一个问题存在:做自己公司的apk开发时 ...
随机推荐
- #启发式合并,LIS,平衡树#洛谷 4577 [FJOI2018]领导集团问题
题目 在一棵树上选择最多的点,使得存在祖先关系的点满足\(w_x\leq w_y\),其中\(x\)是\(y\)的祖先 分析 祖先链上要满足\(LIS\),考虑将子节点的LIS序列合并至节点\(x\) ...
- #线段树,倒序#CF356A Knight Tournament
题目 分析 要求覆盖必须是第一个覆盖的, 考虑最后一个覆盖的很简单做线段树区间赋值, 那么倒序区间赋值就可以了 代码 #include <cstdio> #include <ccty ...
- #后缀数组,单调队列#洛谷 2852 [USACO06DEC]Milk Patterns G
题目 给定一个长度为\(n\)的字符串,求出现至少\(k\)次的最长子串长度 分析 由于后缀排序后的LCP才是最长的,既然要求至少\(k\)次, 实际上也就是维护长度为\(k\)的height数组最小 ...
- OpenHarmony AI框架开发指导
一.概述 1.功能简介 AI 业务子系统是 OpenHarmony 提供原生的分布式 AI 能力的子系统.AI 业务子系统提供了统一的 AI 引擎框架,实现算法能力快速插件化集成. AI 引擎框架主要 ...
- 网上 server2008数据库恢复方法
从网下下载文件有两个:XX_DB_log.ldf 和XX_DB.mdf 首先:文件处理:右键--属性--安全---编辑--勾选"完全控制"--确定--即可.(两个文件都是相同操作) ...
- ASP.NET 部署常见问题及解决方案
ASP.NET 部署部署过程中常见问题及解决方案 Could not load file or assembly 'XXXXX' or one of its dependencies. Access ...
- OpenStack实战安装部署
OpenStack安装部署 一.基础准备工作 部署环境:CentOS 7 64 1.关闭本地iptables防火墙并设置开机不自启动 <span style="color:#33333 ...
- 抓包整理————wireshark 抓包[二]
前言 简单整理一些wireshark抓包. 正文 打开wireshark 的capture的option 选项: 然后可以看到可以捕获的选项: 可以看到这里有我的以太网和虚拟机网卡流量. 这个就是将l ...
- 【Oracle】预定义说明的部分 ORACLE 异常错误(EXCEPTION)
预定义说明的部分 ORACLE 异常错误(EXCEPTION) 参考链接:https://www.cnblogs.com/thescentedpath/p/errordeal.html EXCEPTI ...
- 力扣1075(MySQL)-项目员工Ⅰ(简单)
题目: 项目表 Project: 员工表 Employee: 请写一个 SQL 语句,查询每一个项目中员工的 平均 工作年限,精确到小数点后两位. 查询结果的格式如下: 解题思路: 建表语句: ...