用自动LOD简化3D网格【Babylon.js】

LOD(Level of Details)是一个强大的工具,在 2.0 版本中被添加到 Babylon.js 中。 这个概念相当简单:当相机距网格一定距离时,减少显示的面部数量将提高性能,而用户不会注意到这种减少。

LOD要求开发人员在原始网格上添加一些网格。 创建这些网格的方法之一是简化。 许多 3D 工具提供各种简化算法。 有时称为抽取。

从版本 2.0 开始,Babylon.js 提供了浏览器内简化功能,该功能异步工作,同时尽量不干扰渲染过程。 这些LOD级别将在计算完成后自动添加到场景中。

NSDT工具推荐: Three.js AI纹理开发包 - YOLO合成数据生成器 - GLTF/GLB在线编辑 - 3D模型格式在线转换 - 可编程3D场景编辑器 - REVIT导出3D模型插件 - 3D模型语义搜索引擎 - Three.js虚拟轴心开发包 - 3D模型在线减面 - STL模型在线切割

1、用法 - 简化网格

BABYLON.Mesh 类的任何对象都具有具有以下签名的“simplify”函数:

public simplify(settings: Array<ISimplificationSettings>,parallelProcessing: boolean = true,type: SimplificationType = SimplificationType.QUADRATIC,successCallback?: () => void);

参数说明如下:

settings:设置对象有两个参数:

  • quality - 0.0 到 1.0 之间的数字,定义抽取的百分比(1 表示 100%)
  • distance - 距要添加此 LOD 网格的对象的距离。
  • optimizeMesh(自 2.1 起) - 网格应该优化吗? 可选,默认为 false。 稍后将详细介绍优化。

settings数组的一个简单示例是:

[{ quality: 0.9, distance: 25, optimizeMesh: true },{ quality: 0.3, distance: 50, optimizeMesh: true },
];

对于TypeScript用户和“new”爱好者来说,存在一个 SimplificationSettings 类。 所以,也可以这样做:

const settings: Array<ISimplificationSettings> = []; //in JS: const settings = [];
settings.push(new BABYLON.SimplificationSettings(0.8, 60));
settings.push(new BABYLON.SimplificationSettings(0.4, 150));

parallelProcessing :该代码异步运行。 并行处理标志设置每个级别的处理顺序。 如果设置为 true,则所有内容都将一起运行。 这将使用更多的 RAM(在一段时间内),但通常会运行得更快。 然而,由于帧之间的许多并行计算,FPS 可能会降低到不可接受的水平。 将此标志设置为 false 将处理一个又一个的设置。 这将仅使用一个简化对象,并且将使用更少的 RAM。 然而,这可能需要更长的时间。

type :为了允许实现进一步类型的简化(对于感兴趣的人将在后面解释),应该说明简化的类型。 目前只有一种,BABYLON.SimplificationType.QUADRATIC。 如果类型未定义,这也是默认值。

successCallback :由于这是一个异步函数(立即返回),因此需要回调才能在简化过程结束后运行代码。Auto-LOD 过程成功完成后将调用此函数。

使用示例:

BABYLON.SceneLoader.ImportMesh("", "./", "DanceMoves.babylon", scene, (newMeshes, particleSystems, skeletons) => {newMeshes[1].simplify([{ quality: 0.9, distance: 25 },{ quality: 0.3, distance: 50 },],false,BABYLON.SimplificationType.QUADRATIC,function () {alert("LOD finisehd, let's have a beer!");},);
});

简化完成后,你还可以利用网格类的 getLODLevelAtDistance 和 getLODLevels 函数来访问简化后的网格。 你可以使用它来克隆简化网格并独立于主网格使用它。

2、规则和注意事项

并非所有网格都可以简化。 更好地说 - 所有网格都可以简化,但有些网格不应该简化。

像 Box 这样的对象(如果以最佳方式构建,如 BABYLON.MeshBuilder.CreateBox 函数)没有可以删除的“额外面”。 移除一个面将导致它……不再是一个盒子。

需要遵循的一些“规则”(永远不要忘记,规则就是用来打破的!)

  • 尝试简化具有超过 500 个面的网格。 低于这个数字可能就没有意义。
  • 最适合简化的网格是复杂的对象。
  • 像平面这样的网格在简化后可能会失去形状。
  • 网格质量越低,距离应该越远。 这不应该是线性的 - 简化到 90% 的复杂网格可能看起来仍然几乎相同,但在 30% 时,很明显网格被简化了。 较低质量的简化应该定义较大的距离。
  • 尝试简化代表单个对象的网格。 一个包含许多远处物体的网格会简化得相当差。 LOD 在此类网格上的效果也很差,因为网格的位置实际上并不是所有网格部件的位置。
  • 在开始抽取之前设置网格的材质。 LOD 网格在初始化时使用它们。 如果不设置它们,则预计材料会在达到给定距离时消失。

小技巧:

  • 二次简化可以使用许多因素来计算。 位置、法线、颜色、UV坐标等...因素越多,运行速度就越慢(计算量越多)。 我们决定仅保留位置 - 这意味着简化后,UV 坐标有时会有点偏差。 如果遵循上述规则 4,通常不会引起注意。
  • 网格可能会改变其形状。 对于小平面来说非常引人注目。网格中可能会突然出现“洞”。 使用网格优化可以避免这种情况(从 2.1 开始,面进一步描述)
  • 从 Babylon.js 2.1 开始支持子网格。 由于缺乏边界检测,具有子网格的网格不会被 100% 正确地抽取(参见下一点)。 尝试一下,看看它是否符合你的需求。
  • 边界上的一些三角形将被“删除”。 原因通常是(缺乏)边界检测,这是原始论文的一部分。 由于正确计算所需的时间,该功能未包含在实现中。
  • 使用图像初始化的对象(最好的例子是基于高度图的地面)只会在图像完全加载后才会减少。 为此,请利用它们的 onReady 回调:
const ground = BABYLON.MeshBuilder.CreateGroundFromHeightMap("ground", "textures/heightmap.png", {width: 20, height: 20, subdivisions: 100, onReady: (readyMesh) => {//Simplify mesh herereadyMesh.simplify([{quality: 0.1, distance: 10}]);...
}}, scene);

3、网格优化(从 Babylon.js 2.1 开始)

由于 Babylon 文件格式的性质,许多顶点可能具有相同的位置、法线,但具有不同的颜色/uv 信息。 这给抽取过程带来了问题,抽取过程依赖于改变具有相同位置的所有三角形。

如果你尝试简化网格,但它突然缺少一些三角形,这就是原因 - 你的网格没有针对简化进行“优化”。

有两种类型的优化可用:

  • 全局改变函数,它是 BABYLON.Mesh 的一部分:
mesh.optimizeIndices(function () {//do whatever you want here
});

该选项改变(!)网格的索引顺序。 它速度更快,但可能会更改网格顶点的 UV 坐标。 如果是这种情况,请使用:

  • 简化过程中的优化 - 简化设置现在包含一个新变量:optimizeMesh,它是一个默认为 false 的布尔值。 如果设置为 true,则在网格准备抽取期间将运行不改变网格优化。 简化将在临时顶点数组上运行,并将新顶点的位置与旧的 uv/颜色信息相关联。 这是更好的选项,但也是较慢的选项(对于像演示头骨这样非常大的网格会很明显)

检查哪一种方法最适合你。 两者都有其优点和缺点,为了获得更好的结果,请使用第二个选项(在设置中将 optimizationMesh 设置为 true)。

4、开发进一步的简化算法

如果要添加新的简化算法,需要执行以下几个步骤:

  • 创建一个实现 BABYLON.ISimplifier 接口的类(当然还要实现该函数!:-))
  • 将简化类型添加到 SimplificationType 枚举
  • 在 mesh.simplify 函数中添加类 init (内部函数“getSimplifier”应包含您的类型)。
  • 我们很高兴看到采用你的新简化方案的 PR!

5、直接访问简化类

可以直接访问二次误差抽取并使用其功能,通过创建 QuadraticErrorSimplification 类的对象来做到这一点:

const decimator = new QuadraticErrorSimplification(meshToDecimate);

之后你可以使用以下对象变量:

  • decimationIterations - 抽取过程的最大迭代次数。 简化(通常)会在最大迭代次数之前停止,但实际上一切都取决于下一个变量。 默认值:100。
  • aggressiveness - 决定三角形是否可以删除的阈值是使用此变量决定的。 将其设置为较低的值(例如 2)将导致抽取速度稍慢,但在选择三角形时会更加精确。 将其设置为较高值(例如 15)可能会导致抽取在 1 或 2 次迭代中结束,因为将选择删除大量三角形。 无论如何,一旦达到质量,该过程就会停止。 问题是——它是否选择了更好的三角形来消灭! 默认值:7。
  • syncIterations - 异步迭代内同步迭代的数量。 很难解释,但是较低的数字对性能的影响较小,但会使该过程花费更多的时间。 如果您需要解释,请查看babylon.tools.js 中的AsyncLoop 类或在论坛上联系@raananw。 设置变量后,可以运行简化函数来启动整个过程:
simplify(settings, successCallback);

请参阅上面的解释以了解每个变量的含义。


原文链接:用自动 LOD 简化网格 - BimAnt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/812093.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django中间件路由映射自动加/斜杠问题原因及分析

输入 http://127.0.0.1:8000/main/index/ 输入 http://127.0.0.1:8000/main/index 路由定义情况 urlpatterns [path("index/", views.index) ]可以发现我在输入URL的index路由时&#xff0c;如果没有和Django定义的路由匹配规则一样的话&#xff0c;浏览器自…

Vim:强大的文本编辑器

文章目录 Vim&#xff1a;强大的文本编辑器Vim的模式命令模式常用操作光标移动文本编辑查找和替换 底行命令模式常用操作Vim的多窗口操作批量注释与去注释Vim插件推荐&#xff1a;vimforcpp结论 Vim&#xff1a;强大的文本编辑器 Vim&#xff0c;代表 Vi IMproved&#xff0c;…

如何确保软件通过SmartScreen验证,消除用户下载时的警告提示?

在当前的网络时代&#xff0c;各种软件应用程序深深渗透到人们的日常生活和工作中&#xff0c;许多企业选择自行开发应用程序以推进其业务发展。但在发布应用程序后&#xff0c;软件所有者经常会遇到一个挑战&#xff0c;即用户在下载时可能会遇到微软SmartScreen提示“此应用程…

探索HTTP协议的世界 | 从基础到高级应用,原理与实践相结合(请求篇)

从基础到高级应用&#xff0c;原理与实践相结合 什么是Http历代Http协议主要特点格式和URL协议内容请求行格式如下请求方法简单案例 消息报头报头域的格式HTTP消息报头类型普通报头优化方向报头&#xff08;缓存&#xff09;Cache-Control的选项其他相关的缓存报头 请求报头Acc…

Unity TMP Inputfield 输入框 框选 富文本 获取真实定位

一、带富文本标签的框选是什么 UGUI的InputField提供了selectionAnchorPosition和selectionFocusPosition&#xff0c;开始选择时的光标下标和当前光标下标 对于未添加富文本标签时&#xff0c;直接通过以上两个值&#xff0c;判断一下框选方向&#xff08;前向后/后向前&…

C#Winform使用扩展方法自定义富文本框(RichTextBox)字体颜色

实现效果 调用方法 rtxtLog.AppendTextColorful(richTextBox1,DateTime.Now.ToString(), Color.Red); 完整代码如下 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using Sys…

【U8+】用友固定资产卡片拆分提示:未设置对象变量或With block变量。

【问题描述】 用友U8软件中&#xff0c; 操作固定资产模块&#xff0c;针对资产进行卡片拆分的时候&#xff0c; 提示&#xff1a;未设置对象变量或With block变量。 确定后仍然能打开卡片拆分界面&#xff0c;但是界面显示异常看不到拆分明细信息&#xff0c;并且保存后拆分结…

C/C++ 关于 terminate called without an active exception(问题)

在 C/C 之中这类问题&#xff0c;主要出现在STL两个BCL基础类库使用上面&#xff0c;std::mutex、std::thread&#xff0c;它是指在析构时&#xff0c;某些行为没有被正确处理导致的。 对于 std::mutex&#xff0c;类为析构时&#xff0c;仍旧存在原子信号量标志没有释放&#…

【Qt-Qt Creator使用技巧】

工具-Qt Creator ■ 使用技巧■ 定义触发片段■ Qt Creator 行编辑■ 代码注释■ 代码补全■ 快速给函数添加定义■ 创建书签■ 同步列输入■ 局部替换■ 源代码阅读■ 源码调试■ 使用技巧 ■ 定义触发片段 ■ Qt Creator 行编辑 shift + alt + up / down来获得多个游标。 …

导入芯片原厂SDK Mirror源码到gerrit

下载镜像代码 repo init --mirror --repo-url ssh://xx/repo.git -u ssh://xx/manifests.git -m manifest.xml repo sync 创建AOSP project 对All Project权限修改 创建repo 在刚才下载的codebase根目录执行如下命令&#xff1a; repo forall -c echo $REPO_PROJECT; ssh -p 29…

DOTS Instancing合批:如何针对单个渲染实体修改材质参数

最近在做DOTS的教程,由于DOTS(版本1.0.16)目前不支持角色的骨骼动画&#xff0c;我们是将角色的所有动画数据Baker到一个纹理里面&#xff0c;通过修改材质中的参数AnimBegin,AnimEnd来决定动画播放的起点和终点&#xff0c;材质参数AnimTime记录当前过去的动画时间。但是在做大…

利用Python进行图像和XML标注数据的批量处理

在机器学习项目中,特别是涉及到图像识别和分类的领域,经常需要对大量数据进行预处理。这些数据预处理可能包括图像转换、格式化标签、数据集划分等。本文将介绍一个基于Python的脚本,该脚本能够自动化这些常见任务,并且还支持多进程处理以加速这些操作。 脚本核心功能 该脚…

CSS导读 (元素显示模式 下)

&#xff08;大家好&#xff0c;今天我们将继续来学习CSS的相关知识&#xff0c;大家可以在评论区进行互动答疑哦~加油&#xff01;&#x1f495;&#xff09; 目录 3.6 元素显示模式转换 3.7 (一个小技巧)单行文字垂直居中的代码 3.8 单行文字垂直居中的原理 3.9 小案例…

leaflet知识点:地图窗格panes的应用

一&#xff0c;需求背景 地图中存在无人机&#xff0c;停机坪&#xff0c;航线三个图层&#xff0c;需要实现无人机图层显示在最上面&#xff0c;停机坪图层显示在最下面&#xff0c;航线图层显示在中间。 二&#xff0c;遇到问题 由下图可知航线图层所在overlayPane窗格的z-…

mac下docker搭建nginx+php+mysql,并实现nginx负载均衡

一 环境 系统&#xff1a;macOS Sonoma 14.3芯片&#xff1a;Apple M3 Prodocker 版本&#xff1a;25.0.5 二 软件 OrbStack [推荐&#xff0c;一款轻量化的docker管理软件&#xff0c;还是docker的命令]item2 三 步骤 拉取 nginx 镜像 docker pull nginx新建一个 nginx …

openjudge_2.5基本算法之搜索_1789:算24

题目 1789:算24 总时间限制: 3000ms 内存限制: 65536kB 描述 给出4个小于10个正整数&#xff0c;你可以使用加减乘除4种运算以及括号把这4个数连接起来得到一个表达式。现在的问题是&#xff0c;是否存在一种方式使得得到的表达式的结果等于24。 这里加减乘除以及括号的运算结…

工控 modbusTCP 报文

Tx 发送报文:00 C9 00 00 00 06 01 03 00 00 00 02 Rx 接收报文:00 C9 00 00 00 07 01 03 04 01 4D 00 01 Tx 发送报文:00 C9 00 00 00 06 01 03 00 00 00 02 00 C9 事务处理标识符 2字节 00 00 协议标识符 2字节 固定 00 00 00 06 长度 2字节 表示之后的字节总数 &#xff08;…

大数据之ClickHouse

大数据之ClickHouse 简介 ClickHouse是一种列式数据库管理系统&#xff0c;专门用于高性能数据分析和数据仓库应用。它是一个开源的数据库系统&#xff0c;最初由俄罗斯搜索引擎公司Yandex开发&#xff0c;用于满足大规模数据分析和报告的需求。 特点 开源的列式存储数据库…

elementUI 下拉框加提示文案

效果如下&#xff1a; 展示文案在最下面&#xff0c;跟选项有个分割线 <el-select v-model"value" placeholder"请选择" clearable popper-class"addNotice" class"addNoticeS" visible-change"(v) >selectNotice(v,展示…

Testng测试框架(7)--测试运行

忽略测试 TestNG可以让你忽略类、特殊包、包及其子中的所有Test方法。 当在测试方法级别使用Ignore 注解&#xff0c;在功能上与Test(enabledfalse).一样。 以下例子将忽略类中所有tests。 import org.testng.annotations.Ignore; import org.testng.annotations.Test; Ign…