在 Unity 中平滑动态生成的网格? [英] Smooth dynamically generated mesh in Unity?

查看:29
本文介绍了在 Unity 中平滑动态生成的网格?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个 Unity & 网格C#(它本身是通过合并更简单的基础网格实时创建的),我们如何在运行时*将它变成一个平滑的,几乎就像包裹在布中一样的网格版本?不是完全凸出的版本,而是更圆润、柔化锋利边缘、弥合深缝隙等.当平滑角度"法线设置应用于导入的对象时,表面看起来也很理想.谢谢!

Given a mesh in Unity & C# (that itself was created in realtime by merging simpler base meshes), how could we during runtime* turn it into a smooth, almost like wrapped-in-cloth mesh version of itself? Not quite a fully convex version, but more rounded, softening sharp edges, bridging deep gaps and so on. The surface would also ideally look like when the "smoothing angle" normals setting is applied to imported objects. Thanks!

之前&草图后

*网格设置是由人制作的,其细节事先未知.虽然它的所有基本形状部分(在我们合并它们之前)都是已知的.如果这有助于解决方案,基础部分也可能保持未合并状态,如果有一个运行时解决方案可以快速应用包装混搭,即使基础部分随着时间的推移改变它们的变换,但静态一次性转换,那将是非常棒的也会很棒.

*The mesh setup is made by people and its specifics unknown beforehand. All its basic shape parts (before we merge them) are known though. The base parts may also remain unmerged if that helps a solution, and it would be extra terrific if there was a runtime solution that would fastly apply the wrapper mash even with base parts that change their transform over time, but a static one-time conversion would be great too.

(一些相关的关键词可能是:Marching cube algorithm & metaballs、skin above bone、meshfilter转换、平滑着色器、软化、顶点细分.)

(Some related keywords may be: marching cube algorithm & metaballs, skin above bones, meshfilter converting, smoothing shader, softening, vertices subdivision.)

推荐答案

有很多方法可以获得类似的东西,所以你可以选择你喜欢的一种:

There are many ways to get something similar so you can pick your preferred one:

行进立方体

这个算法很容易使用,但结果总是继承了它的块状风格".如果那是您想要的外观,请使用它.如果您需要更平滑和/或像素完美的东西,请寻找其他方法.

This algorithm is easy to use but the result always inherits the blocky 'style' of it. If that's the look you want then use it. If you need something more smooth and/or pixel perfect then look for other ways.

射线行进和有符号距离函数

这是一个非常有趣的技术,可以给你很多控制.您可以使用简单的立方体/圆柱体等来表示您的基础部件.方程并用简单的数学将它们混合在一起.

This is quite interesting technique that may give you a lot of control. You can represent your base parts with simple cube/cylinder/etc. equations and blend them together with simple math.

在这里你可以看到一些例子:http://iquilezles.org/www/articles/distfunctions/distfunctions.htm

Here you can see some examples: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm

这里最好的事情是设置非常简单,您甚至不需要合并基础部分,只需将数据推送到渲染器即可.更糟糕的是,渲染部分可能会变得计算困难.

The best thing here is that it's very simple to setup, you don't even need to merge your base parts, you just push your data to renderer. Worse, is that it may get computationaly hard on rendering part.

老式网格修改

在这里您有最多的选择,但也最复杂.您从自己没有太多数据的基础部分开始,因此您可能应该使用 CSG 联合操作将它们连接到一个网格中.

Here you have the most options but it's also most complicated. You start with your base parts which don't have much data by themselves so you should probably join them into one mesh using CSG Union operation.

有了这个网格,你就可以为你的基元计算邻居数据:

Having this mesh you can compute neighbors data for your primitives:

  • 为每个顶点找到包含它的三角形.
  • 为每个顶点找到包含它的边.
  • 为每条边找到包含它的三角形.

使用此类数据,您可以执行以下操作:

With such data you may be able to do things like:

  • 找到并切割一些尖锐的顶点.
  • 找到并切割一些锋利的边缘.
  • 移动顶点以最小化它创建的三角形/边之间的角度.

等等...

确实有很多细节可能对你有用,你只需要测试一些看看哪个给出了首选的结果.

There are really a lot of details that may work for you or not, you just need to test some to see which one gives the preferred results .

我要从一件简单的事情开始:

One simple thing I'd start with:

  • 对于每个顶点,找到通过任何边连接到它的所有顶点.
  • 计算所有这些顶点的平均位置.
  • 使用 [0,1] 范围内的一些 alpha 参数来混合初始顶点位置和平均位置.
  • 实现此算法的多次迭代并为其添加参数.
  • 对 alpha 和迭代次数进行实验.

使用这种方式,您还有两个不同的阶段:计算和渲染,因此使用动画可能会变得太慢,但仅渲染网格会比使用 Ray Marching 方法更快.

Using this way you also have two distinct phases: computation and rendering, so doing it with animation may become too slow, but just rendering the mesh will be faster than in Ray Marching approach.

希望这会有所帮助.

不幸的是,我从来没有这样的需求,所以我没有任何示例代码,但这里有一些伪代码可以帮助您:

Unfortunately I've never had such need so I don't have any sample code but here you have some pseudo-code that may help you:

你有你的网格:

Mesh mesh;

顶点邻居数组:

对于任何顶点索引NtriNeighbors[N] 将存储由边连接的其他顶点的索引

For any vertex index N, triNeighbors[N] will store indices of other vertices connected by edge

List<HashSet<int>>     triNeighbors = new List<HashSet<int>>();

int[] meshTriangles = mesh.triangles;
// iterate vert indices per triangle and store neighbors
for( int i = 0; i < meshTriangles.Length; i += 3 ) {
    // three indices making a triangle
    int v0 = meshTriangles[i];
    int v1 = meshTriangles[i+1];
    int v2 = meshTriangles[i+2];
    int maxV = Mathf.Max( Mathf.Max( v0, v1 ), v2 );

    while( triNeighbors.Count <= maxV )
        triNeighbors.Add( new HashSet<int>() );

    triNeighbors[v0].Add( v1 );
    triNeighbors[v0].Add( v2 );

    triNeighbors[v1].Add( v0 );
    triNeighbors[v1].Add( v2 );

    triNeighbors[v2].Add( v0 );
    triNeighbors[v2].Add( v1 );
}

现在,对于任何单个顶点,使用索引 N 您可以计算其新的平均位置,例如:

Now, for any single vertex, with index N you can compute its new, averaged position like:

int counter = 0;
int N = 0;
Vector3 sum = Vector3.zero;
if( triNeighbors.Count > N && triNeighbors[N] != null )
{
    foreach( int V in triNeighbors[N] ) {
        sum += mesh.vertices[ V ];
        counter++;
    }
    sum /= counter;
}

这段代码中可能有一些错误,我刚刚补上了,但你应该明白这一点.

There may be some bugs in this code, I've just made it up but you should get the point.

这篇关于在 Unity 中平滑动态生成的网格?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆