有很多方法可以获得类似的东西,因此您可以选择自己喜欢的:
行进方块
这个算法很容易使用,但结果总是继承了它的块状“风格”。如果那是您想要的外观,请使用它。如果您需要更平滑和/或像素完美的东西,请寻找其他方法。
Ray Marching 和有符号距离函数
这是一种非常有趣的技术,可以让您进行大量控制。您可以用简单的立方体/圆柱体/等来表示您的基础部件。方程式并将它们与简单的数学混合在一起。
这里你可以看到一些例子:
http://iquilezles.org/www/articles/distfunctions/distfunctions.htm
这里最好的一点是设置非常简单,您甚至不需要合并基础部分,只需将数据推送到渲染器即可。更糟糕的是,它可能会在渲染部分变得难以计算。
老式网格修改
这里有最多的选择,但也最复杂。您从自己没有太多数据的基础部分开始,因此您可能应该使用 CSG 联合操作将它们连接到一个网格中。
有了这个网格,你就可以为你的图元计算邻居数据:
- 为每个顶点找到包含它的三角形。
- 为每个顶点找到包含它的边。
- 为每条边找到包含它的三角形。
等等
有了这些数据,您或许可以做以下事情:
- 找到并切割一些尖锐的顶点。
- 找到并切割一些锋利的边缘。
- 移动顶点以最小化它创建的三角形/边之间的角度。
等等……
确实有很多细节可能对你有用,你只需要测试一些,看看哪一个给出了首选的结果
.
我会从一件简单的事情开始:
- 对于每个顶点,找到通过任何边连接到它的所有顶点。
- 计算所有这些顶点的平均位置。
- 使用 [0,1] 范围内的一些 alpha 参数在初始顶点位置和平均位置之间进行混合。
- 实现此算法的多次迭代并为其添加参数。
- 使用 alpha 和迭代次数进行实验。
使用这种方式,您还有两个不同的阶段:计算和渲染,因此使用动画可能会变得太慢,但仅渲染网格会比使用 Ray Marching 方法更快。
希望这会有所帮助。
编辑:
不幸的是,我从来没有这样的需要,所以我没有任何示例代码,但这里有一些伪代码可以帮助你:
你有你的网格:
Mesh mesh;
顶点邻居数组:
对于任何顶点索引N,triNeighbors[N]将存储由边连接的其他顶点的索引
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 计算其新的平均位置,例如:
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;
}
此代码中可能存在一些错误,我只是弥补,但您应该明白这一点。