一个网格合并(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开发时 ...
随机推荐
- OpenHarmony中的HDF单链表及其迭代器
概念 为了性能考虑,嵌入式系统一般使用C语言进行开发,由于C语言标准库没有封装链表,所以嵌入式系统一般自己设计和实现链表这种数据结构.单链表是链表中的一种,本文描述OpenAtom OpenHarmo ...
- dev DEV控件:gridControl常用属性设置
引用:https://www.cnblogs.com/kingsliu/articles/6145679.html 1.隐藏最上面的GroupPanelgridView1.OptionsView.Sh ...
- Linux编译静态库、动态库
一.Linux上编译静态库 # 1.编译成.o文件 gcc -c a.c b.c // 2.编译成静态库 ar -r liba.a a.o b.o // 3.链接成可执行文件 gcc main.c - ...
- Kalman滤波器的原理与实现
Kalman滤波器的原理与实现 卡尔曼滤波器(Kalman Filter)是一个十分强大滤波器,虽然叫做滤波器,卡尔曼滤波器其实可以起到到两个作用,即预测与更新,这与我们在其运行时所关注的环节有关.当 ...
- 推荐几款Vue后台管理系统的框架,以便备用
推荐几款Vue后台管理系统的框架,以便备用 Vue.js 是一个目前比较流行的前端框架,在业界也算很有名气,今天这里为大家罗列一下基于Vue的后端管理的框架. 使用这些框架你会发现它包括了我们常用的路 ...
- BI、OLAP、多维分析、CUBE 这几个词是什么关系?
这些词我们在建设分析型应用时经常会听到,这几个词也经常被弄混,这里来梳理一下. BIBI 是 Business Intelligence(商业智能)的缩写,是指企业利用已有数据进行数据分析从而指导商业 ...
- VulnHub-ical打靶记录
这绝对是最简单的一个题目了. 目标发现 netdiscover -r 192.168.0.10/24 根据靶场和本地系统的网段进行扫描. 信息收集 nmap -sV -Pn -sT -sC -A 19 ...
- pytest接口自动化搭建经验
前言:目前公司的主要产品是一个web类型的产品:需要做一些自动化,目前的想法是只做接口自动化,不做ui的一个自动化,目前的思路是先对主流程做正常校验,后期再对每一个接口做校验: 一.版本信息: pyt ...
- 如何解决打不开Microsoft Store的痛处?
换了机房后,我最喜欢的计算器和画图3d没有了,网上的方法都行不通,怎么办? 第一步,在百度上搜索你想安装的东西,例如我搜索的画图3d,就会有这个链接. 然后,把这个链接复制到这个网站的搜索框中,就会有 ...
- 通过Jenkins构建CI/CD实现全链路灰度
简介: 本文介绍通过 Jenkins 构建流水线的方式实现全链路灰度功能. 作者:卜比 本文介绍通过 Jenkins 构建流水线的方式实现全链路灰度功能. 在发布过程中,为了整体稳定性,我们总是希 ...