我正在尝试构建一个.PLY解析器,将存储为.ply文件的3d模型加载到半边数据结构网格中。
对不起这个大问题,我非常啰嗦,我想确保列出所有细节。因此,我将立即重申我的最终目标,这样用户可以看到在阅读后面的巨大文本块之前可以了解我想要的内容。
1)从.PLY文件的顶点和面部列表中记忆半边缘的好哈希
或
2)是否有更好的方法从.PLY文件中的数据填充我的半边结构?
.PLY文件列出顶点,然后是网格的面。显而易见的解决方案是首先填充顶点表,然后使用面列表生成边表。问题是每个边都有一个伙伴边,因此对于四边形网格,第一个四边形I加载将需要8个半边。这不是最初的问题,只需为面部创建四个半边并反转每个边以使其伙伴成为半边。这里的问题是,这会产生4个悬垂的半边,与4个不同的面相关联。
因此有两种攻击方法:首先生成面的所有边,然后尝试配对伙伴边。我真的不喜欢这种方法,它似乎在程序上效率较低,因为它将涉及大量的搜索和排序。
第二步:按照第一个说明进行:从指定的第一个面开始并生成创建多边形所需的边,并且创建边时也会创建它们的双胞胎。但是,我们将记住边缘列表,因此所有边都将散列到表中。然后,当我们为其他面生成边时,如果已生成边(因为它是前一个加载面的伙伴边),我们将只是从表中抓取指针。
这就是我被困住的地方。我需要一个智能散列函数来记忆我的边缘列表。需要最小化碰撞以提高效率。我现在想到的方案是基于创建它们的两个顶点命名*边缘,IE边缘01和10是双胞胎。最糟糕的情况是创建一个哈希表,其中所有顶点都可能被连接,这将最终为2 ^ n,其中n =顶点数,这是完全不可察觉的。我的目标是使哈希值接近实际边缘的数量(=每个面的边数之和),同时仍然最小化碰撞。
*注意:因为半边强制执行“逆时针仅”绘制方案,所以不可能发生名称冲突。通过基于绘制它们的两个顶点命名边缘,我们确保所有名称对于单个半边缘都是唯一的。
答案 0 :(得分:2)
我很啰嗦
你可能想要了解一些事情。
具有边缘的一种简单方法是通过其两个顶点的索引。为了使其唯一,首先采用较小的索引,然后采用较大的索引。像这样:
uint hash(const Vertex& v1, const Vertex& v2)
{
int i1 = v1.index;
int i2 = v2.index;
if (i1 > i2)
swap(i1, i2);
return (i1 | (i2 << 16));
}
在此哈希表指向的实际数据中,您可能希望跟踪您已经看到的哪一对以及您期望的哪一对(相反的一对)。
答案 1 :(得分:0)
您是在边缘存储索引或引用吗?如果你使用incides,就不会像
这样简单的哈希函数19 * index0 + 7 * index1
“足够好”?如果你的哈希值应该是对称的,那么我会考虑两个索引的简单异或,但是由于半边缘确实是直接的,你可能最好使用非对称哈希并专门寻找成对的边缘方向。 / p>
实际上比较两个边缘是一个相对便宜的操作(即比生成一个复杂的哈希便宜),碰撞并不像你看起来那样令人厌恶。
就是说,根据我的经验。准备在这里被真正的哈希专家烧掉。 : - )
作为旁注:您可能希望确保您的哈希表实现与删除相当,因为删除表中找到的任何配对边缘可能会有所收获。