如何根据其位置遍历网格顶点?

时间:2018-11-09 15:43:32

标签: c# unity3d mesh traversal point-clouds

我正在使用Point Cloud Free Viewer在Unity中可视化点云。它具有一个脚本,它可以解析.off文件并创建网格而不进行三角剖分。但是,由于索引格式为16位,因此代码创建了多个网格。我修改了利用32位格式的代码,并获得了200万点的网格:

enter image description here

我想做的是创建一个像几何图形一样的网格,并根据点密度为该点云着色。我想通过乘以最大x和最小x,y,z值之间的差异来找到该点云的大致体积,并将该体积分成相等的框。这些盒子中的每个盒子都会根据它们包含的点数来上色。如果有人可以帮助我,我会很高兴。我尝试了KDTree方法,但是它有点慢,因为我有200万点。在创建网格之前,我还尝试了对点进行排序,但是这也花费了太多时间。有没有一种方法可以基于位置遍历网格顶点而无需访问所有顶点(考虑它们是随机索引的)?我相信我正在寻找mesh.bounds.contains()之类的解决方案,但我不知道是否存在诸如空间搜索之类的方法。

3 个答案:

答案 0 :(得分:1)

不是一个完整的解决方案,实际上是对我追求的方向的暗示:首先将顶点池划分为较小的组,例如,将其划分为多维数据集(可能是分离的网格),对其进行预先计算,然后只需要在一个很大的范围内进行搜索即可在初步搜索了一组与您的区域相邻(或触摸)的立方体之后。

答案 1 :(得分:1)

在我看来,您想要一个octree

首先,将所有点加载到内存中(200万个点实际上并不多-假设是两倍,即2,000,000 * 3 * 8字节〜= 45 MB)。解析文件并将点加载到内存时,请记录最小和最大x,y和z坐标。然后,您可以在N * LogN中建立限制该体积的八叉树。然后,对于每个网格体积,您可以非常快速地查询树以仅获取该区域中的点。我很确定这是做您想要的事的最有效方法。

我建议检查quadtree文章中queryRange的实现,以了解如何实现。八叉树只是四叉树的3-d实现,因此底层代码大致相同(每个节点包含8个子节点,而不是4个子节点)。

答案 2 :(得分:0)

对于那些以后可能会问这个问题的人,我根据Nico的评论找到了一个非常快速的解决方案。我正在通过使用此脚本解析扫描文件来遍历整个点

 for (int i = 0; i < numPoints; i++)
    {
        buffer = sr.ReadLine().Split();

        points[i] = new Vector3(float.Parse(buffer[0]) , float.Parse(buffer[1]) , -float.Parse(buffer[2]) );

        //Finding minX, minY, minZ
        if (points[i].x < minX)
            minX = points[i].x;
        if (points[i].y < minY)
            minY = points[i].y;
        if (points[i].z < minZ)
            minZ = points[i].z;
        //Finding maxX, maxY, maxZ
        if (points[i].x > maxX)
            maxX = points[i].x;
        if (points[i].y > maxY)
            maxY = points[i].y;
        if (points[i].z > maxZ)
            maxZ = points[i].z;

    }

这是我和我一起使用的变量FindPointIndex

    deltaX = maxX - minX;
    deltaY = maxY - minY;
    deltaZ = maxZ - minZ;
    gridCountX = Mathf.CeilToInt(deltaX / gridSize);
    gridCountY = Mathf.CeilToInt(deltaY / gridSize);
    gridCountZ = Mathf.CeilToInt(deltaZ / gridSize);
    Resolution = gridCountX * gridCountY * gridCountZ;
    Histogram = new int[Resolution];

 int FindPointIndex(Vector3 point)
{
    //Finds the grid index of the point 
    int index = Mathf.FloorToInt((point.x - minX) / gridSize) + ((Mathf.FloorToInt((point.z - minZ) / gridSize)) * gridCountX)
           + Mathf.FloorToInt((point.y - minY) / gridSize) * gridCountX * gridCountZ;
    if (index < 0)
    {
        index = 0;
    }
    return index;
}

然后我可以再次遍历这些点以增加每个点的索引,以查看每个网格持有这样的点数:

 for (int i = 0; i < numPoints; i++)
    {
        Histogram[FindPointIndex(points[i])]++;                                      
    }

最后使用此直方图,我可以用另一个循环为点云着色。