作为当前项目的一部分,我需要在Unity中为网格生成哈希。这些用于以后检查网格内容是否已更改。出于接口考虑,不幸的是,哈希必须采用字符串形式。
我目前的方法如下:
public override string GetHash()
{
StringBuilder hash = new StringBuilder();
hash.Append("v");
foreach (Vector3 val in this.v)
{
hash.Append(val.ToString());
}
hash.Append("n");
foreach (Vector3 val in this.n)
{
hash.Append(val.ToString());
}
hash.Append("u");
foreach (Vector2 val in this.u)
{
hash.Append(val.ToString());
}
hash.Append("v");
foreach (int val in this.t)
{
hash.Append(val.ToString());
}
return hash.ToString();
}
事实证明这是一个很大的瓶颈,主要是由于Vector3.ToString()调用。 (对于立方体原语,大约为4-5ms)。
还有更多高效的方法可以对仍然对网格中的微小变化敏感的网格进行哈希处理吗?
[Vector3
是Vector3
,并且如果struct
具有相同的值,则其GetHashCode
实现将返回相同的哈希值:
Vector3
所以通常,我宁愿将哈希计算作为public override int GetHashCode()
{
return this.x.GetHashCode() ^ this.y.GetHashCode() << 2 ^ this.z.GetHashCode() >> 2;
}
并仅将int
作为最后一步返回:
string
此外,我也不知道您的确切用例,但对顶点位置进行散列可能就足够了。
我建议使用类似的东西
public override string GetHash()
{
var output = 0;
foreach (Vector3 val in this.v)
{
// e.g. using bitwise XOR
output = output ^ val.GetHashCode();
}
foreach (Vector3 val in this.n)
{
output = output ^ val.GetHashCode();
}
foreach (Vector2 val in this.u)
{
output = output ^ val.GetHashCode();
}
foreach (int val in this.t)
{
output = output ^ val.GetHashCode();
}
return output.ToString();
}