3D网格细分与变形

news2024/11/15 11:48:09

这篇文章探讨了整个细分和变形过程中出现的各种问题的解决方案。然后,它将其扩展为完整的管道,用于变形和操纵 3D 网格,并计算着色和位移的精确法线。

1、简单细分

在 3D 渲染中,所有网格都由三角形组成。当模型从 Blender 或任何其他 3D 建模应用程序中导出时,该应用程序会将该网格分解为一组三角形,3D 引擎渲染后会将其转换为一个或多个对 GPU 的绘制调用。

对于我的用例,我希望能够细分任何 3D 网格,并能够使用导出后的 3D 数据来执行此操作。这个想法是将一组三角形变成更多、更小的三角形。一种简单的方法是取每个面积大于某个阈值的三角形,然后通过分割其最长边将其切成两半。

这是经过 2 轮细分后在 Blender 中的样子:

是的,这真的没有什么突破性。你可以通过其他方式进行细分,例如在中心添加一个顶点,然后通过向现有顶点绘制新边将其分成三个,或者你想要的任何方式。这只是将三角形变成更小的三角形。

最好的部分是它有效!我实现了一些简单的代码来执行此操作,将其应用于一些简单的测试网格,发现它们看起来……完全一样。

这正是在这种情况下应该发生的事情,因为我们实际上并没有改变几何体的整体形状 - 只是将其分成更小的部分。

2、变形 + 位移

现在我已经分割了网格,我想我应该测试一些基本的变形。

变形(deformation)一词实际上并不意味着对网格拓扑进行了什么样的更改。我说它的主要意思是网格顶点的位置正在以某种方式改变,从而改变网格的结构。

移动它们时,重要的是避免破坏网格的拓扑结构,因为面相互夹在一起或向后扭曲(因为渲染时只有面的正面是可见的)。由于 3D 网格可以呈现任意数量的复杂形状,因此通常不清楚以特定方式移动特定顶点会对整个网格产生什么影响。

执行此操作的一个好方法是沿其法线移动顶点。如果你不熟悉,我很快会更多地谈论法线,但概念是顶点根据其在网格表面上的局部角度向内或向外移动。

对于本文的其余部分,我将把沿其法线移动顶点称为位移​​(displacement)。

3、位移贴图

在 3D 图形中,位移贴图是一种通过基于从某些纹理(位移贴图)读取的值修改顶点着色器中顶点的位置来为网格添加更多几何细节的方法。

该过程本身也非常简单。每个顶点沿着其法线向量向前或向后移动,具体取决于该顶点的位移贴图中的值,使用专用 UV 贴图查找。

以下是 Three.JS 用于实现它的完整着色器代码,供参考:

transformed += normalize(objectNormal) * (texture2D(displacementMap, vDisplacementMapUv).x * displacementScale + displacementBias);
不过,这种简单性是有代价的。

为了使位移贴图看起来不错,通常需要另一组贴图,如法线贴图或凹凸贴图。如果缺少这些贴图,几何图形的变化将不会与阴影对齐,镜面高光和阴影等东西会看起来不协调甚至完全中断。

4、简单的细分位移结果

我没有使用位移贴图,而是对顶点着色器进行了小幅调整,只对网格中的每个顶点应用一个向外的恒定位移。这更像是一次健全性检查,以确保细分确实像我预期的那样工作。

当我在 Three.JS 场景中设置好所有内容时,我看到了以下内容:

(左)原始模型 (右)位移模型

如你所见,它绝对没有像我预期的那样工作。要理解为什么会出现这种情况,需要对 3D 图形的工作方式有一定的了解。

5、法线

对于本文的其余部分(以及一般的 3D 图形)来说,一个极其重要的概念是法线。法线(normal)或法线向量是垂直于其他物体的角度。对于三角形或平面等物体,它们的法线从其正面“射出”。

顺便说一句,我很好奇这些东西是如何被命名为“法线”的。

事实证明,2000 多年来,人们一直将直角称为“法线”。使用法线来表示常规或标准似乎要年轻得多。很奇怪。

在 3D 图形中,法线被分配给顶点。每个顶点都会获得一个法线,它是所有共享它的面的平均值。 Blender 是一款功能极其丰富的应用程序,它内置了对网格上不同类型法线的可视化支持。以下是之前渲染的立方体的一部分:

浅蓝色线是面法线,深蓝色线是通过平均附加面法线产生的顶点法线,洋红色线称为“分割”或“循环”法线。我稍后会详细讨论这些。

6、平滑 + 平面着色

无论如何,法线对 3D 渲染如此重要的主要原因之一是它们对着色的影响。用于模拟光与表面相互作用方式的大多数方程式都依赖于了解被照亮的表面与光源之间的角度以及表面与相机之间的角度。法线对于实现这一点至关重要。

法线还提供了在平滑(smooth)和平坦(flat)着色模型之间切换的能力。使用平滑着色,根据每个片段与其每个三角形顶点的距离对法线进行插值。这使得每个片段的计算法线在整个网格表面上连续。

以下是平滑着色(左)和平坦着色(右)的比较:

对于平坦着色,每个片段的法线都设置为面的法线。这意味着需要为每个面创建唯一的顶点 - 即使这些顶点位于完全相同的位置 - 因为它们需要分配唯一的法线。

我之前测试位移的立方体是从 Blender 导出的,带有平坦着色。这绝对适合该网格;它的所有面都彼此成非常锐利的角度,如果试图平滑这些角度,会让它看起来很奇怪。然而,这正是破坏位移的原因。

为了便于平坦着色,Blender 需要在立方体的每个角上复制 3 个顶点。它们具有完全相同的位置,但它们的法线不同,以匹配它们所使用的三角形。这就是之前 Blender 屏幕截图中那些洋红色线条所代表的。它们显示了在应用当前着色模型的情况下导出的网格中将存在的不同法线。

如果使用这些洋红色分割法线来位移顶点,则效果是同一起点的顶点将移动到不同的终点。

要使位移起作用,必须计算新的法线,以便将同一位置的顶点移动到同一目的地,从而使网格保持粘合在一起。

7、LinkedMesh数据结构

此时,我意识到我需要以比我迄今为止使用的“只是一堆三角形”系统更复杂的方式表示网格。

在阅读过去遇到的各种帖子和库时,我听到很多关于半边(halfedge)数据结构的提及。这是一种表示 3D 网格的方法,通常由“严肃的”几何库和工具使用。它将网格表示为图形,其组成部分(顶点、边和面)都指向彼此。 “半边”用于指代围绕面的两个顶点之间的边的单一方向。

我四处寻找,看看能否在 Rust 中找到一个记录良好且维护良好的半边库,但我没有找到任何有吸引力的东西。

因此,我决定实现自己的  LinkedMesh 数据结构来表示网格。

它类似于半边数据结构,并且在许多方面都简化了半边数据结构,但有一些其他区别:

  • 没有独立的顶点或边。所有顶点都必须是边的一部分,所有边都必须是面的一部分。
  • 所有面都是三角形;没有 N 边。
  • 边上没有隐式方向。相反,面只保存对组成它们的 3 个顶点的有序引用列表。

就像半边数据结构一样,它维护不同实体之间的双向链接,如下所示:

拥有这样的表示使得许多与操作网格相关的事情变得更容易和/或更高效。

例如,获取与其他面接壤的所有面的列表变得非常容易:只需遍历其所有 3 条边的面列表即可。即将出现的多个事情都对这个数据结构至关重要。

8、LinkedMesh实现细节

与其余代码一样,我在 Rust 中实现了 LinkedMesh。尽管人们经常谈论由于借用检查器的工作方式,在 Rust 中构建链接数据结构很困难,但 slotmap crate 使这几乎不成问题。

你不是将指向其他实体的指针存储在其中,而是将特殊标记的索引存储在专用堆中 - 就像竞技场分配一样。这会增加一点开销,但它还提供了额外的检查,可以防止使用对具有相同索引的实体的陈旧引用等错误。

这是因为 SlotMap 键包含一个版本,该版本在每次更新索引时都会递增,因此插入到重复使用的索引中的新实体将具有与以前存在的旧实体不同的键。仅这一点就为我节省了大量开发和调试数据结构的时间。

除此之外,在实施过程中确实没有太多特别的事情发生。有一些棘手的错误需要解决,包括在更新图表中的内容后忘记更新或刷新引用,但我最终让一切正常。

整个东西也存在于一个文件中,这使得它易于设置和使用。我添加了一些方法来将 LinkedGraph 导入/导出到索引三角形的缓冲区 - 我之前使用的原始数据格式。

9、计算单独的着色 + 位移法线

现在回到手头的问题。我们必须处理的网格数据在同一位置有多个顶点,以便于着色。但是,用于位移的法线对于所有重合顶点都必须相同。

为了支持非平滑着色和有效位移,必须计算两组单独的法线。

为了计算位移的法线,需要将那些重合的顶点合并在一起。为了实现这一点,我只是对网格中的每个(顶点,顶点)对进行了强力二次搜索。如果这两个顶点位于完全相同的点,则它们会合并 - 更新所有边和面中的引用以指向第一个,然后从图中删除第二个。

对于我正在处理的网格,这已经足够快了,N^2 性能特征并不重要。毕竟这是在原始低分辨率、预细分网格上运行的。

如果/当我最终将其用于更大、更复杂的网格时,就需要使用一些空间分区数据结构(如 BVH)来加快速度。

10、图关系

由于 LinkedMesh 数据结构在各方面都是图(graph),因此可以将其可视化。我编写了一些代码来构建 LinkedMesh 的 GraphViz 表示 - 最初用于调试目的。

这是同一网格的图表示,其中两个方面从之前开始以直角连接在一起:

请注意,有两个不同的、不相连的子图。每个子图恰好有两个面,因为一个矩形由两个三角形组成。这两个三角形恰好共享一条边,而所有其他边都只包含在一条边中。

如果执行了重合顶点的合并,则结果图如下:

正如预期的那样,子图合并在一起,没有断开的组件。两个合并的顶点现在有 4 条边 - 与我们在 Blender 中对网格进行三角剖分时看到的一致:

11、计算顶点法线

现在所有重合点都已合并到图形表示中,我们可以计算合并顶点上的精确顶点法线,这样移动它们不会导致网格面彼此拉开。

之前,我提到这是通过平均连接面的法线来实现的,这是真的。然而,当我自己实现这个时,我了解到实际上有一个更具体的算法需要遵循。

顶点法线需要通过对连接面的法线取加权平均值来计算,权重是共享该顶点的面的边缘之间的角度。

写下来听起来有点复杂,但实际上非常简单。直观地看到它会有所帮助:

红色和蓝色圆弧标记正在测量的角度,这是计算法线时共享所选顶点的两个面的法线的加权值。

如果不执行加权,法线在某些几何体上会不平衡且不准确,并产生错误/不均匀的着色和位移结果。

12、按角度平滑着色

顶点合并后可获得准确的位移法线,但有关哪些面是平滑的、哪些面是平坦的原始着色数据会丢失。这会使整个网格平滑着色。如果需要任何其他类型的着色,我们必须自己计算。

在计算着色法线时,实际上除了我迄今为止讨论的二进制“平滑”或“平坦”之外还有更多选项。Blender(我相信其他工具也是如此)提供了一个名为“按角度平滑着色”(以前标记为“自动平滑着色”)的选项:

这种着色模型是平滑和平面着色的混合体。它查看面之间的边缘角度,如果角度大于某个可配置阈值,则将边缘标记为“锐利”。这本质上具有复制该边缘顶点的效果 - 反转上一步的合并过程。这允许共享该锐利边缘的面在其上具有不同的法线,并使边缘在渲染时呈现平面着色。

这似乎很简单,对吧?

在我花了整整一个周末试图想出一个从头开始执行此操作的算法之前,我就是这么想的。

我尝试了各种想法,最有希望的是图形遍历类型的方法,我将以图形的形式遍历网格并沿着平滑的面行走并构建彼此都平滑的面的子图。

所有这些方法至少在某些地方都失败了,产生了各种奇怪的错误着色伪影,如下所示:

最后,我不得不承认失败,并寻求专家来找到一种算法。

我在 Blender 源代码中找到了他们为网格执行此操作的 位置,弄清楚了发生了什么,并用 Rust 为 LinkedMesh 自己实现了它。

他们那里的代码相当晦涩难懂,充满了我没有的功能或平台实现细节的处理,但我最终弄清楚了发生了什么。

他们使用的算法非常巧妙。其核心是围绕顶点走动并将面划分为他们所谓的“平滑扇形”。每个平滑扇形都有自己的顶点副本,具有独特的着色法线。

还有更多内容,如果你感兴趣的话,这是关于该算法及其实现方式的专门文章。

这里唯一需要注意的重要一点是,当我复制一个顶点以使其其中一个边缘变得锐利时,先前计算的位移法线将被复制到新的顶点。这确保了无论重复顶点分配了什么着色法线,它们都会以相同的方式位移,并且网格不会被撕裂。

13、程序化位移

好了,到目前为止,我有了以下内容:

  • 一种将任意三角形集转换为类似图形的 LinkedMesh 表示的方法
  • 一种合并重合顶点和计算位移法线的算法,以使网格在位移时不会撕裂
  • 一种计算“按角度平滑”法线以进行着色的算法
  • 一种细分生成的 LinkedMesh 以增加几何细节而不改变其形状的算法

现在我们可以实际进行一些位移了。

我决定提前在 CPU 上实现位移/变形,而不是像以前那样在顶点着色器中执行此操作。

这样做有几个原因:

  • 它允许运行更复杂/更昂贵的算法。
  • 它允许使用有关网格的非本地数据,而不仅仅是单个顶点

也许最有影响力的是,

  • 它还允许计算和更新除顶点位置之外的其他内容

如前所述,顶点着色器中的位移贴图受到渲染过程后期发生的事实的限制。如果你在没有相应的法线贴图或其他匹配项的情况下显着位移网格的顶点,结果看起来会很不理想。

由于我现在有了成熟的按角度平滑法线计算代码,我可以随心所欲地进行网格变形,然后从头开始计算准确的法线。

14、基于噪声的位移

我首先尝试的是基于噪声的位移算法。我在网格中每个顶点的位置采样了一个 4 个八度的 3D FBM 噪声场,并根据采样值沿其法线推或拉顶点。

结果如下:

相当成功,如果我自己这么说的话。这是一个有点极端的例子,位移量非常大,但这有助于夸大位移后法线计算对阴影和着色的影响。

15、水晶状突起

我想尝试另一种位移算法,它将有助于利用算法的动态平面着色能力。

我修改了基于噪声的方法,使其根据阈值急剧位移,如下所示:

let displacement = if noise > -0.9 && noise < -0.7 { 1. } else { 0. };

结果如下:

按角度平滑着色的效果已完全显现。

查看尖刺与网格表面连接处的底部。由于突出的角度较大,这些边缘被标记为锐利,结果是面之间形成了漂亮的平面阴影区别。

当我在这里看到结果时,我立即想到了各种其他可以尝试的东西。

我可以多次重复位移过程以在网格上构建越来越多的细节,我可以使用构造实体几何体将多个简单网格组合在一起,然后位移合并的结果……这个系统可以实现很多东西。

不过这篇文章已经很长了,所以我会把所有这些东西留到下次再说。

16、其他注意事项

以下是我在网格处理流程中发现的一些修复或调整小技巧的列表,这些技巧在某些情况下可以使事情变得更好或看起来更好。

  • 着色法线计算顺序

我在进行最小或无位移的细分时注意到一件事,有时三角形着色伪影会出现在以平滑角度相交的平面之间的边缘上:

我花了很长时间试图找出我的正常计算算法中是否存在错误或其他问题。但事实证明,这实际上是底层几何体的正确着色行为。当我在 Blender 中手动重新创建类似的几何体时,出现了类似的三角形伪影:

对于某些三角形图案,法线计算的工作方式自然会在光照中产生这些方格图案。

幸运的是,有一种方法可以解决这个问题。对于遇到此问题的网格,我发现在预细分网格上计算着色法线,然后以与位移法线相同的方式插入这些法线可以完全解决问题。

这基本上复制了着色器在渲染一个大三角形并将过渡扩展到整个面时所做的相同行为。

  • 保留锐利边缘

我注意到的另一件事是,有时应用变形会导致之前锐利的边缘变得平滑或部分平滑,而平滑的角度法线随后被计算。法线计算代码工作正常,但对于某些网格,结果看起来有点不对劲。

为了解决这个问题,我在位移之前标记了锐利边缘,并在整个细分和变形过程中保留了该锐利标记。

3D 建模师有时会手动执行此操作 - 明确将某些边缘标记为尖锐,即使它们的角度是平滑的 - 以便调整模型的着色方式。以下是它对我测试的一些网格的影响:

效果有点微妙,但它确实有助于使某些网格看起来更干净,并更好地保留其原始结构。

  • 位移法线插值方法

如果你还记得,进行此位移的过程涉及合并重合顶点,然后计算这些合并顶点的位移法线。之后,网格被细分以添加更多细节,然后进行位移。

我没有提到的一件事是如何为细分过程创建的新顶点计算位移法线。

我最初的解决方案是仅对分割的每个边的位移法线进行插值,并将其设置为在中间创建的新顶点。

事实证明,这对于我正在进行的变形类型最有效。但是,它可以为几何体创建一种“充气屋”外观。当使用此方法将每个顶点沿其法线向外位移一个常数时,它看起来是这样的:

明白我的意思了吗?它们看起来就像充气过度的气垫床。

公平地说,这是应用的相当极端的位移量,因此对于其他网格来说不会那么明显。

我想到另一种设置细分过程中创建的新顶点的位移法线的方法是将它们设置为边缘法线。只需平均共享边缘的所有面的法线即可提前计算边缘法线。

以下是使用该方法的同一场景的外观:

顶部现在是平的,但几何形状不太平滑,并且在边缘处产生了一些大面。

无论如何,我建议首先使用插值位移法线,并且仅在你的特定位移方法需要时才使用第二种方法。

  • UV 贴图 + 三平面贴图

你可能已经注意到,对于我在本文中包含的所有屏幕截图,尽管底层网格严重扭曲,但网格上的纹理并没有出现拉伸或扭曲。

原因是我使用三平面贴图对它们进行纹理处理。三平面贴图是一种可用于纹理网格的算法,根本不需要 UV 贴图。相反,它使用世界空间坐标并对 X、Y 和 Z 轴进行 3 次不同的查找。它根据被纹理化的片段处的网格法线进行插值,从而产生(大部分)平滑且自然的网格表面纹理。

如果不使用三平面贴图,则在进行细分时必须考虑 UV 贴图,并计算位移过程中产生的新顶点的插值 UV 坐标。如果变形程度较轻,则可能可以避免这种情况,但对于更极端的变形,这可能会导致网格上出现可见的拉伸效果。

不过,我强烈建议你尝试三平面贴图;当我第一次开始使用它时,它对我来说非常神奇。据我所知,这几乎是纹理化复杂的程序生成网格的唯一方法。而且它确实非常容易实现;即使是我添加了一些功能和性能优化的花哨实现也只有几十行代码

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

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

相关文章

关于window的安装

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 第一windows的分类 旗舰版 个人版…

赶快收藏!全网最佳 WebSocket 封装:完美支持断网重连、自动心跳!

文章目录 一、WebSocket 基础WebSocket 的基本使用 二、封装 WebSocket 客户端WebSocketClient 类使用 WebSocketClient 类解释代码实现 三、总结优点未来改进 &#x1f389;欢迎来到SpringBoot框架学习专栏~ ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff…

找不到mfc140u.dll怎么修复,mfc140u.dll丢失的多种修复方法

计算机丢失mfc140u.dll文件会导致依赖该文件的软件无法正常运行。mfc140u.dll是Microsoft Visual C 2015的可再发行组件之一&#xff0c;它属于Microsoft Foundation Class (MFC) 库&#xff0c;许多使用MFC开发的程序需要这个DLL文件来正确执行。丢失了mfc140u.dll文件。会导致…

论文阅读--《FourierGNN:从纯图的角度重新思考多元时间序列预测》

Yi K, Zhang Q, Fan W, et al. FourierGNN: Rethinking multivariate time series forecasting from a pure graph perspective[J]. Advances in Neural Information Processing Systems, 2024, 36. 本次介绍的文章来自NeurIPS 2023&#xff0c;关于多变量时间序列的预测 摘要…

以创新赋能引领鸿蒙应用开发,凡泰极客亮相华为HDC2024

6月21日至23日&#xff0c;华为开发者大会2024在松山湖举行。大会现场&#xff0c;华为发布了HarmonyOS、盘古大模型等方面最新进展。国内外众多企业齐聚一堂&#xff0c;共迎新商机、共创新技术、共享新体验。 凡泰极客作为鸿蒙生态的重要战略合作伙伴&#xff0c;同时也是鸿…

【 IM 服务】开通全量消息路由服务

前提条件 在生产环境中&#xff0c;仅 IM 旗舰版、IM 尊享版可开通该服务。 操作说明 控制台 - 应用配置 - IM 服务管理 页面开通 可自助配置&#xff08;配置名&#xff1a;多设备消息同步&#xff09;收费配置&#xff08;开发环境下免费&#xff09; image1575645 48.4 K…

安达发|生产计划排产软件推动制造业的高质量发展

在全球经济一体化的大背景下&#xff0c;制造业正面临着前所未有的挑战与机遇。随着智能化技术的不断进步&#xff0c;生产计划排产软件作为推动制造业高质量发展的重要工具&#xff0c;已经成为行业转型升级的关键。 制造业作为国民经济的重要支柱&#xff0c;其发展水平直接关…

2024年全国VUE考试中心大全!

大家好&#xff0c;华为HCIA、HCIP、HCIE的笔试部分&#xff0c;都需要在VUE考试中心进行预约。但是很多同学都不知道当地VUE考试中心在哪里&#xff01; 为了解决大家的问题&#xff0c;这边整理了全国各大城市的VUE考试中心名称和详细地址。需要的小伙伴们可以来看看&#x…

项目实训-vue(十一)

项目实训-vue&#xff08;十一&#xff09; 文章目录 项目实训-vue&#xff08;十一&#xff09;1.概述2.页顶导航栏3.导航信息4.总结 1.概述 本篇博客将记录我在图片上传页面中的工作。 2.页顶导航栏 <divstyle"display: flex;justify-content: space-between;alig…

2732. 找到矩阵中的好子集

题目 给你一个下标从 0 开始大小为 m x n 的二进制矩阵 grid。 从原矩阵中选出若干行构成一个行的非空子集&#xff0c;如果子集中任何一列的和至多为子集大小的一半&#xff0c;那么我们称这个子集是好子集。 更正式的&#xff0c;如果选出来的行子集大小&#xff08;即行的…

考研数学|线代零基础,听谁的课比较合适?

线性代数是数学的一个重要分支&#xff0c;对于考研的学生来说&#xff0c;掌握好这门课程是非常关键的。由于你之前没有听过线性代数课&#xff0c;选择一个合适的课程和老师就显得尤为重要。 以下是一些建议&#xff0c;希望能帮助你找到合适的课程资源。 首先&#xff0c;…

迁移方案详解|使用YMP从异构数据库迁移到YashanDB

数据迁移简介 01典型场景与需求 在国产化浪潮下&#xff0c;数据库系统的国产化替代成为了一个日益重要的议题&#xff0c;有助于企业降低对外依赖&#xff0c;提升信息安全和自主性。 以Oracle、MySQL为代表的传统关系型数据库管理系统&#xff0c;在企业应用中占据了重要的…

食品供应链管理商城系统的设计、实现和代码

上线食品供应链管理商城系统的设计与实现是一项复杂且重要的任务&#xff0c;它不仅涉及到技术层面的具体实现&#xff0c;还包括业务流程的优化和用户体验的提升。本文将从系统设计、功能模块、技术选型以及实现步骤等方面进行详细探讨。 ### 系统设计 在设计食品供应链管理…

cad转换pdf怎么转换?介绍四个转换方法

cad转换pdf怎么转换&#xff1f;在数字化办公日益盛行的今天&#xff0c;CAD图纸的转换与处理成为许多专业人士不可或缺的技能。特别是在需要将CAD图纸转换为PDF格式时&#xff0c;一款功能强大的软件能够大大提高工作效率。今天&#xff0c;就为大家推荐四款CAD转PDF的神器&am…

Docker 安装Nginx部署网站 防火墙端口 数据卷挂载

拉取镜像 docker pull nginx#不写版本号 表示最新版本查看是否拉取成功 docker images#成功 nginx latest 605c77e624dd 2 years ago 141MB mysql 8.0 3218b38490ce 2 years ago 516MB mysql latest 3218b38490ce 2 years ago 5…

【乐吾乐2D可视化组态编辑器】水位随数据动态变化

External Player - 哔哩哔哩嵌入式外链播放器 示例&#xff1a;进度条&#xff0c;通常用来展示水位变化 乐吾乐2D可视化组态编辑器demo&#xff1a;https://2d.le5le.com/ 示例&#xff1a;乐吾乐2D可视化 (le5le.com)

项目实训-vue(十三)

项目实训-vue&#xff08;十三&#xff09; 文章目录 项目实训-vue&#xff08;十三&#xff09;1.概述2.处理按钮 1.概述 本篇博客将记录我在图片上传页面中的工作。 2.处理按钮 实现了图片的上传之后&#xff0c;还需要设置具体的上传按钮。 这段代码使用 Element UI 的 …

使用API有效率地管理Dynadot域名,为文件夹中的域名进行域名停放

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

探讨数字化背景下VSM(价值流程图)的挑战和机遇

在信息化、数字化飞速发展的今天&#xff0c;各行各业都面临着前所未有的挑战与机遇。作为源自丰田生产模式的VSM&#xff08;价值流程图&#xff09;&#xff0c;这一曾经引领制造业革命的工具&#xff0c;在数字化背景下又将如何乘风破浪&#xff0c;应对新的市场格局和技术变…

linux用户使用资源限制

linux用户使用资源限制 1. 概述2. 特殊权限&#xff08;SUID,SGID,SBIT&#xff09;3. 访问控制列表&#xff08;ACL&#xff09;4. 磁盘空间限制&#xff08;quota&#xff09;5. 进程资源限制5.1 ulimit5.2 cgroup 前言&#xff1a;linux是一个遵循POSIX的多用户、多任务、支…