Unity中Mesh重叠顶点合并参考及其应用
在Unity中,如果将一个模型文件(比如从max里面导出一个fbx文件)导入到编辑器中之后,Unity会把所有在原来在面列表中公用的顶点复制一份,保证每个三角形使用的顶点都是单独的,不与其它三角形共用顶点,Unityh这么做应该有他的道理,但我尚未想明白Unity这么做的原因是什么。
但是考虑到在有些应用中使用共用顶点能够更好的处理一些问题,这里写了一个将Unity中Mesh重叠顶点合并成公用顶点的代码,目的是将位置重叠的顶点去掉,同时也将面列表的内容更新,由一个原来有重叠顶点的Mesh获得一个新的使用公用顶点的Mesh,参考如下:
Mesh GetWeldMesh(Mesh mesh)
{Vector3[] vs = mesh.vertices;int[] ts = mesh.triangles;Debug.Log(ts.Length);Dictionary<Vector3, int> dicVert = new();for (int i = 0; i < ts.Length; i++){bool hasSamePos = false;Vector3 vert = vs[ts[i]];foreach (var kv in dicVert){Vector3 key = kv.Key;if (vert == key){if (kv.Value < ts[i]){ts[i] = kv.Value;}else{dicVert[kv.Key] = ts[i];}hasSamePos = true;break;}}if (!hasSamePos){dicVert.Add(vert, ts[i]);}}List<Vector3> listVertice = new();foreach (var kv in dicVert){listVertice.Add(kv.Key);}Mesh meshNew = new(){vertices = vs,triangles = ts};meshNew.RecalculateNormals();return meshNew;
}
目前我能想到的这么做的用处有两个,第一个是在一种描边方法中,Shader需要将要描边的物体增加一次渲染,在这次渲染中,Shader会将网格的每个顶点沿着该顶点的法线方向向外挤出一点点,形成一个更大的轮廓,然后反面渲染,这样就形成了原物体的勾边效果,不过这里有个问题,如果使用的Unity默认的Mesh,当物体的光滑组是连续的时候,挤出的效果是没问题的,当光滑组不连续(例如一个Box),顶点挤出后会出现分离问题。你当然可以在类似max这种软件中将Box的光滑组强行编成一组,这样导入Untiy中之后挤出效果倒是没问题了,但是本身显示效果就不是硬边的效果了,这也不对啊。但是如果在使用Shader渲染Mesh的时候,使用的不是原始的Mesh,而是通过上述代码生成的新的Mesh,由于顶点是共用的,就不存在出现挤出分离的问题。关于具体的Shader就不说了,玩过Shader的都懂。
第二个是查找物体的边界,一般来说查找物体边界的方法是找到不被两个三角形共用的边,但是Unity中Mesh默认所有的顶点都是单独被面列表使用的,根本没有所谓被两个三角形共用的边的情况,这中情况会发现所有的三角形的边都是边界,貌似行不通,所以还是需要上述方法将Unity中Mesh重叠顶点合并再去查找边界。其查找边界的代码参考如下(由于Mesh的编辑可能不止一组,所以用的返回值是List<int[]>,是顶点编号数组的列表):
List<int[]> GetEdgeIndexes(Mesh mesh){Vector3[] vs = mesh.vertices;int[] ts = mesh.triangles;Dictionary<Edge, int> dicEdge = new();for (int i = 0; i < ts.Length; i += 3){int indexA = ts[i];int indexB = ts[i + 1];int indexC = ts[i + 2];bool hasSameEdge01 = false;bool hasSameEdge02 = false;bool hasSameEdge03 = false;KeyValuePair<Edge, int>[] kvs = dicEdge.ToArray();for (int j = 0; j < kvs.Length; j++){Edge edge = kvs[j].Key;if (edge.IsSame(indexA, indexB)) { hasSameEdge01 = true; dicEdge[edge] += 1; continue; }if (edge.IsSame(indexB, indexC)) { hasSameEdge02 = true; dicEdge[edge] += 1; continue; }if (edge.IsSame(indexC, indexA)) { hasSameEdge03 = true; dicEdge[edge] += 1; continue; }}if (!hasSameEdge01) { dicEdge.Add(new Edge(indexA, indexB), 1); }if (!hasSameEdge02) { dicEdge.Add(new Edge(indexB, indexC), 1); }if (!hasSameEdge03) { dicEdge.Add(new Edge(indexC, indexA), 1); }}List<Edge> edges = new List<Edge>();foreach (var kv in dicEdge){if (kv.Value == 1){edges.Add(kv.Key);}}foreach (var item in edges){Debug.Log(item.a + " , " + item.b);}List<int[]> listEdgeIndexes = new();while (edges.Count > 0){List<int> listTriangle = new(){edges[0].a,edges[0].b};edges.RemoveAt(0);while (true){int indexLast = listTriangle[^1];bool hasAddIndex = false;for (int i = 0; i < edges.Count; i++){Edge edge = edges[i];if (indexLast == edge.a){listTriangle.Add(edge.b);hasAddIndex = true;edges.RemoveAt(i);break;}if (indexLast == edge.b){listTriangle.Add(edge.a);hasAddIndex = true;edges.RemoveAt(i);break;}}if (!hasAddIndex){listEdgeIndexes.Add(listTriangle.ToArray());break;}}}return listEdgeIndexes;}
其中所用到的Edge类代码如下:
public class Edge
{public readonly int a;public readonly int b;public Edge(int a, int b){this.a = a;this.b = b;}public bool IsSame(Edge edge) { return (a == edge.a && b == edge.b) || (a == edge.b && b == edge.a); }public bool IsSame(int a, int b) { return (a == this.a && b == this.b) || (a == this.b && b == this.a); }
}
下图将一个球体挖了三个洞洞,通过上述方法查找到边界,并用LineRenderer渲染了边界。

相关文章:
Unity中Mesh重叠顶点合并参考及其应用
在Unity中,如果将一个模型文件(比如从max里面导出一个fbx文件)导入到编辑器中之后,Unity会把所有在原来在面列表中公用的顶点复制一份,保证每个三角形使用的顶点都是单独的,不与其它三角形共用顶点…...
倚光科技助力自由曲面设计与加工
近年来,自由曲面因其在光学、汽车、航空航天等领域的广泛应用,受到设计师和工程师的高度关注。自由曲面作为一种具有更高自由度的非球面透镜,能够在光学系统中实现更加精确的光线控制,优化像差校正,并且在满足功能需求…...
PWM调节DCDC参数计算原理
1、动态电压频率调整DVFS SOC芯片的核电压、GPU电压、NPU电压、GPU电压等,都会根据性能和实际应用场景来进行电压和频率的调整。 即动态电压频率调整DVFS(Dynamic Voltage and Frequency scaling),优化性能和功耗。 比如某SOC在…...
[Pro Git#3] 远程仓库 | ssh key | .gitignore配置
目录 1. 分布式版本控制系统的概念 2. 实际使用中的“中央服务器” 3. 远程仓库的理解 4. 新建远程仓库 5. 克隆远程仓库 6. 设置SSH Key 实验 一、多用户协作与公钥管理 二、克隆后的本地与远程分支对应 三、向远程仓库推送 四、拉取远程仓库更新 五、配置Git忽略…...
Freertos任务切换
一、操作系统进行任务切换的时机: 采用信号量实现任务的互斥: 二、FreeRTOS 任务切换场合 PendSV 中断的时候提到了上下文(任务)切换被触发的场合: ● 可以执行一个系统调用 ● 系统滴答定时器(SysTick)中断。 1、执行系统调用 执行系统…...
go开发中interface和方法接收器的使用
Go 语言中的接口和方法接收器学习 Go 中的 interface 就像是一个神奇的魔法杖,能让你轻松地将不同的类型拉到同一个阵营里。与其他语言的接口不同,Go 的接口无需显式声明“我实现了你”,只要你满足了接口规定的方法,Go 就会自动认…...
vue3-tp8-Element:对话框实现
效果 参考框架 Dialog 对话框 | Element Plus 具体实现 一、建立view页面 /src/views/TestView.vue 二、将路径写入路由 /src/router/index.js import { createRouter, createWebHistory } from vue-router import HomeView from ../views/HomeView.vueconst router create…...
高中数学:随机变量-正态分布
文章目录 一、连续性随机变量二、大致图像三、正态分布图像及解析式图像特点均值与方差公式正态分布各区域概率 一、连续性随机变量 二、大致图像 三、正态分布图像及解析式 图像特点 均值与方差公式 正态分布各区域概率...
游戏引擎学习第47天
仓库: https://gitee.com/mrxiao_com/2d_game 昨天我们花了一点时间来修复一个问题,但基本上是在修复这个问题的过程中,我们决定添加一个功能,那就是在屏幕上控制多个实体。所以如果我有一个手柄,我可以添加另一个角色࿰…...
Git 仓库托管教程
git远程仓库 常用的远程仓库-->托管服务:github、码云、gitlab等 github需要魔法上网,速度较慢因为在国外且仅仅支持Git,如果不是Git项目是不支持的;码云--gitee国内的代码托管平台,服务器在国内速度快一些&#…...
基于51单片机的简易时钟/定时器闹钟proteus仿真
地址: https://pan.baidu.com/s/1uez4cwZuXpchmihmRqnLEg 提取码:1234 仿真图: 芯片/模块的特点: AT89C52/AT89C51简介: AT89C52/AT89C51是一款经典的8位单片机,是意法半导体(STMicroelectro…...
Jackson @JsonProperty 注解
1. 概述 Jackson 是一个流行的Java库,用于将Java对象转换为JSON格式以及从JSON反序列化回Java对象。一种常见的需求是在序列化为JSON或从JSON反序列化时自定义字段的命名。Jackson 的 JsonProperty 注解正好满足了这一需求。 JsonProperty 注解概览 JsonProperty…...
【Excel学习记录】02-单元格格式设置
1.单元格格式工具美化表格 单元格格式位置 选中单元格,右键→设置单元格格式 合并居中 跨越合并 字体类型、大小、颜色、填充底纹、边框 斜线 软回车:alt enter 格式刷 2.单元格数字格式 格式不影响数值,只是展示形式 日期本质也是数…...
支持自定义离线地图地理区域,查询组件及数据源功能增强,DataEase开源BI工具v2.10.3 LTS发布
2024年12月9日,人人可用的开源BI工具DataEase正式发布v2.10.3 LTS版本。 这一版本的功能变动包括:数据源方面,API数据源和Excel数据源支持对字段类型和长度进行设置;图表方面,离线类地图支持自定义地理区域设置&#…...
LF CRLF
这个提示的含义是:Git 检测到你当前的 file3.txt 文件中使用了 LF(换行符,Line Feed,\n) 作为换行符,但在你系统的 Git 配置中,指定要将其转换为 CRLF(回车换行,Carriage…...
【从零开始入门unity游戏开发之——C#篇01】理论开篇,理解什么是编程
文章目录 前言前置条件进制什么是十进制、二进制二进制有什么用?为什么计算机用二进制而不用十进制?二进制转十进制十进制转二进制二进制运算 计算机中的数据存储单位什么是编程?什么是代码?什么是编程语言?常见的编程…...
怎样提升企业网络的性能?
企业网络的稳定性和高效性直接影响员工的工作效率。以下从多维度分析了一些有效策略,帮助公司提升网络性能,营造更高效的办公环境。 1. 升级网络设备 采用性能更高的网络硬件是优化网络体验的重要基础。选择支持高吞吐量、低延迟的设备(如企业…...
1. 机器学习基本知识(2)——机器学习分类
1.4 机器学习分类 1.4.1 训练监督 1. 监督学习:已对训练数据完成标记 分类:根据数据及其分类信息来进行训练,使模型能够对新的数据进行分类 回归:给出一组特征值来预测目标数值 2. 无监督学习:没有对训练数据进行任…...
四叉树算法在游戏碰撞检测中的应用
简介 在游戏开发中,碰撞检测是一个非常重要但计算成本较高的环节。如果采用简单的暴力检测方法,需要对场景中的每个物体与其他所有物体进行碰撞检测,时间复杂度为O(n)。四叉树(Quadtree)算法通过空间划分的方式,可以显著降低碰撞…...
IDEA 打包普通JAVA项目为jar包
需求:普通java项目(有添加依赖的jar包),没有用maven管理依赖和打包,要打成jar包,包可以用“java -jar 包名” 启动程序。 讲如何打包前,先记录下普通项目的目录结构和怎么添加依赖包 1.目录结…...
对比按次计费Taotoken的TokenPlan套餐为长期项目带来的成本变化
🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 对比按次计费与Taotoken的TokenPlan套餐为长期项目带来的成本变化 在持续运营的AI项目中,成本的可预测性与可控性是团队…...
同事悄悄告诉我,他月薪比我高1.8万,岗位一模一样。我去问HR,HR说,薪资保密。我才明白,保密的从来不是他的,是我的
最近看到一个帖子,有人说,他在公司干了三年,一直以为自己的薪资还算正常,直到有一天,关系不错的同事喝多了,把工资条拍给他看。两个人同一天入职,同一个岗位,同一个绩效评级。差了1.…...
Vue3组件传参大全,各种传参方式的对比
在 Vue3 的日常开发中,组件间的数据传递与通信是最基本的操作。面对不同的组件关系(父子、祖孙、兄弟、任意组件)和不同的交互需求(单向、双向、共享状态、跨层级透传),Vue3 提供了丰富而灵活的传参方案。本…...
ABAP云迁移中SAML Bearer断言实战指南
1. 这不是“配置一下就能用”的流程——SAML Bearer Assertion 在 ABAP 云迁移中到底在替谁干活?你刚接手一个 SAP S/4HANA Cloud 扩展项目,客户要求“把本地 ABAP 系统里的用户身份,安全地透传到新上线的 Node.js 微服务里”。运维同事甩来一…...
实战指南:如何构建企业级Chrome自动化测试环境
实战指南:如何构建企业级Chrome自动化测试环境 【免费下载链接】chrome-for-testing 项目地址: https://gitcode.com/gh_mirrors/ch/chrome-for-testing Chrome for Testing 是Google专为浏览器自动化测试设计的专业解决方案,解决了传统Chrome版…...
3大核心技术:解密QMC音频文件的最优方案
3大核心技术:解密QMC音频文件的最优方案 【免费下载链接】qmc-decoder Fastest & best convert qmc 2 mp3 | flac tools 项目地址: https://gitcode.com/gh_mirrors/qm/qmc-decoder 在数字音乐版权保护日益严格的今天,QQ音乐采用的QMC加密格式…...
苏州晟雅泰电子:关于长鑫存储与兆易创新的关系
长鑫存储(及其母公司长鑫科技)与兆易创新的关系极为紧密,是由一位核心人物——董事长朱一明联结而成的深度战略联盟。这两家公司在股权、人事和业务等多个层面相互绑定,形成了“一个核心、两个支点”的独特格局。以下是其关系的具…...
09_AI审计平台设计:从风险识别出发而非从底稿编号出发
09 AI审计平台设计:从风险识别出发而非从底稿编号出发摘要:如果你打开一个审计系统,首页显示的是E1000、E2000、E3000这些底稿编号,那这个系统的设计者一定没搞明白审计师每天到底在想什么。我做了八年审计系统UX设计,…...
CargoBay源码解析:深入理解块(block)式API的实现原理
CargoBay源码解析:深入理解块(block)式API的实现原理 【免费下载链接】CargoBay The Essential StoreKit Companion 项目地址: https://gitcode.com/gh_mirrors/ca/CargoBay CargoBay是一个功能强大的iOS StoreKit辅助库,它为Apple的应用内购买框…...
解放双眼:如何用ebook2audiobook将电子书变成专业有声读物
解放双眼:如何用ebook2audiobook将电子书变成专业有声读物 【免费下载链接】ebook2audiobook Generate audiobooks from e-books, voice cloning & 1158 languages! 项目地址: https://gitcode.com/GitHub_Trending/eb/ebook2audiobook 你是否曾经在通勤…...
