正常行进立方体为每个立方体找到12条边,但您可以对每个立方体执行3条边,将边保存在数组中,然后再次遍历立方体,引用相邻立方体的边,而不是计算它们。
引用相邻立方体的过程在互联网上没有明确讨论,因此欢迎任何使用行进立方体的人来帮助找到解决方案的细节。你已经知道一个实现了吗?
这张图显示了每个立方体需要的3条黄色边,而不是12条边。
编辑-我刚刚找到了这个解决方案,尽管它只是其中的一部分:
想象有3条边来自立方体的角落,坐标最低。那么所有其他边只属于其他立方体。如果我们的立方体有坐标(x,y,z),那么相邻的钻孔立方体就有坐标(x+1,y,z),(x,y+1,z),(x,y,z+1),(x+1,y+1,z),(x+1,y,z+1),(x,y+1,z+1)。你可以把边想象成一个向量。然后立方体的角点有边(1,0,0),(0,1,0),(0,0,1)。具有坐标(x+1,y,z)的立方体具有属于我们的立方体的边(0,1,0)和(0,0,1)。立方体(x+1,y+1,z)只有一条属于我们的立方体的边(0,0,1)。因此,如果你为立方体存储了4个元素,你可以像这样访问它们:
edge1 = cube[x][y][z][0];
edge2 = cube[x][y][z][1];
edge3 = cube[x][y][z][2];
edge4 = cube[x+1][y][z][1];
edge5 = cube[x+1][y][z][2];
edge6 = cube[x][y+1][z][0];
edge7 = cube[x][y+1][z][2];
edge8 = cube[x][y][z+1][0];
edge9 = cube[x][y][z+1][1];
edge10 = cube[x+1][y+1][z][2];
edge11 = cube[x+1][y][z+1][1];
edge12 = cube[x][y+1][z+1][0];
现在,edge7连接了哪些点?答案是(x,y+1,z)和(x,y+1,z)+(0,0,1)=(x,y+1,z+1)。
现在,edge7连接哪些多维数据集?这更难。我们看到坐标z是沿着边变化的,这意味着我们的立方体有相同的z坐标。现在所有其他的坐标都改变了。在我们有+1的地方,立方体有很大的坐标。在我们有+0的地方,立方体的坐标更小。所以边连接了立方体(x,y,z)和(x-1,y+1,z)。具有相同边的另外两个立方体是(x,y+1,z)和(x-1,y,z)。
-==--=-=--=-
EDIT2-所以我正在做这件事,并不是那么简单。我有一个循环,它同时计算8个点,12条边,边的插值,位值和一个顶点边的值,所有这些都在一个循环中。
所以我在它之前做了一个新的循环,以计算尽可能多的内容,并将其放在数组中,以便在复杂的循环中使用。
我可以在数组中沿着边回收交叉点的插值值,尽管我将不得不在复杂的循环中重新计算所有点,因为我用来决定位号的点的值引用了顶点表格中的值。这让我很困惑!我想,一旦我有了边交叉值,我就可以直接使用这些值来获得三角表,而不必重新计算这些点!
事实上,没有。无论如何,这是另一个已经做过的人的信息,只要它是可读的!http://www.new-npac.org/projects/sv2all/sv2/vtk/patented/vtkImageMarchingCubes.cxx滚动到这一行:立方体负责他们最小面上的边缘。
发布于 2015-04-18 23:48:21
以您建议的方式减少边计算的一个简单方法是计算立方体,每次计算一个轴对齐的平面。
如果您将所有立方体及其边都保存在内存中,则只需计算一次边并通过索引查找相邻边将很容易。但是,由于空间要求,您通常不希望一次将所有立方体都保存在内存中。
一种解决方案是一次计算一个立方体平面。即,轴对齐的横截面,从一侧开始并向相反侧进行。然后,您只需要在内存中一次最多保留两个完整的立方体平面。在每个平面中移动时,可以参考上一个平面中的共享边和当前平面中以前计算的立方体。当你移动到下一个飞机时,你可以解除分配你不再需要的飞机。
编辑:本文将讨论如何按照我的建议进行编辑:http://alphanew.net/index.php?section=articles&site=marchoptim&lang=eng
发布于 2014-02-13 13:21:04
有趣的是,当我实现自己的my时,我想出了类似的解决方案。
当你开始使用MC时,你把它们当作一个不同的立方体,但如果你想获得高性能,你需要创建整个网格作为一个整体,在这里创建顶点索引等并不容易。当你想要添加平滑的逐顶点法线时,它变得更加有趣:)。
为了解决这个问题,我创建了一个简单的索引缓存机制来存储每个边的顶点索引。然后,对于每个计算的边,我有立方体位置x,y,z和边索引,我这样做:
For each axis:
if the edge is on '+' side of axis:
replace edge index with its '-' side sibling
increment cube position along axis
这个简单的操作给出了正确的立方体位置和边缘索引0,1,2。然后,我通过简单的位循环从x,y,z,edgeIndex值计算出总的缓存索引。
当我有缓存索引时,我会检查它是否大于-1。如果是,那么在这条边上有一个已经计算过的顶点,我可以重用它。如果它是-1,我需要创建一个新的顶点并将其索引存储在缓存中。这样,您将只计算每个顶点一次,甚至可以添加包含顶点的每个三角形之间共享的法线值。
发布于 2020-11-02 14:03:02
是的,我想我做的和kolenda类似。我有一个结构,有5个int:(cube)index和4个vertexindices (A,B,C,D)。
对于最内部的循环(x),我只有lastXCache和nextXCache。在指向-x方向的4条边上,我询问lastXCache.A != -1,如果是,分配先前计算的值,依此类推。在+x方向,我将计算的顶点存储在nextXCache中。当立方体完成时: lastXCache = nextXCache;对于y和z方向,它需要是一个列表(可变数组的单位项),下一个y是下一行(所以大小),下一个z是下一个平面(所以大小*大小)
唯一的缺点是,它必须以这种方式连续地运行多维数据集。但是你可以并行计算不同的块。
另一种我认为可以更并行的方法是需要2次遍历: 1.计算每个立方体的3条边,当1条边完成时,-> 2.绘制三角形。
我真的不知道哪种方法更好,但它的实际工作方式似乎足够快。使用unity工作会更好。为1块/网格创建一个IJob。
https://stackoverflow.com/questions/16055829
复制相似问题