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

查看:130
本文介绍了在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.

(一些相关的关键字可能是:行进立方体算法和元球,骨头上方的皮肤,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:

行军方块

Marching Cubes

此算法易于使用,但结果始终继承其块状的样式".如果这是您想要的外观,请使用它.如果您需要更平滑和/或更完美的像素,请尝试其他方法.

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.

射线行进和符号距离函数

Ray Marching and Signed Distance Functions

这是一种非常有趣的技术,可以给您很多控制权.您可以用简单的立方体/圆柱体等来表示基本零件.方程,并通过简单的数学将它们融合在一起.

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.

老派网格修改

Old school mesh modifications

在这里,您有最多的选择,但也最复杂.您从基础部件本身没有太多数据开始,所以您可能应该使用CSG Union操作将它们连接到一个网格中.

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 .

我将从一件事开始:

  • 对于每个顶点,找到通过任意边连接到它的所有顶点.
  • 计算所有这些顶点的平均位置.
  • 使用[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;

顶点邻居数组:

对于任何顶点索引 N triNeighbors [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天全站免登陆