【发布时间】:2018-11-20 15:55:15
【问题描述】:
我一直在尝试优化如何在 Quad Sphere 的顶面和底面与其余面中查找四叉树面的邻居。我尝试了几种方法来确定邻居,最新的方法提高了查找速度,但我想知道是否有更好的方法
方法一:
保留所有四边形使用的所有顶点的所有用户的查找表,然后,对于每个四边形,找到与原始四边形共享边顶点的不是祖先的任何其他四边形(减去角顶点,因为它们是共享的由多个非邻居)。这对于少量的细分和顶点非常有效,但是随着每个细分和顶点的增加,性能会变得更差。 请参阅此实现的示例:https://github.com/bicarbon8/QuadSphere/blob/master/Assets/Scripts/QuadVertMap.cs#L104
方法二:
在每个细分级别保留所有四边形的查找表,按级别索引,然后对于每个四边形,找到同一级别或低一级(父级)的不是祖先的任何其他四边形,并检查它们的边顶点以查看它们是否与原始 Quad 的边顶点匹配。这比方法 1 效果更好,但如果你在细分级别太深,它仍然会受到影响。这看起来像下面的代码 sn-p:
public Quad FindNeighbor(Quad quad, EdgeType edge)
{
Vector3[] edgeVerts = quad.GetWorldVerts(quad.GetEdgeVerts(edge));
int level = quad.GetLevel(); // neighbors can only be equal or 1 lower level
List<Quad> potentialNeighbors = Quads[level].Where(n => n != quad).ToList();
if (potentialNeighbors.Any())
{
foreach (Quad potentialNeighbor in potentialNeighbors)
{
var topEdge = potentialNeighbor.GetWorldVerts(potentialNeighbor.GetEdgeVerts(EdgeType.Top));
if (topEdge.All(v => edgeVerts.Contains(v)))
{
return potentialNeighbor;
}
var bottomEdge = potentialNeighbor.GetWorldVerts(potentialNeighbor.GetEdgeVerts(EdgeType.Bottom));
if (bottomEdge.All(v => edgeVerts.Contains(v)))
{
return potentialNeighbor;
}
var leftEdge = potentialNeighbor.GetWorldVerts(potentialNeighbor.GetEdgeVerts(EdgeType.Left));
if (leftEdge.All(v => edgeVerts.Contains(v)))
{
return potentialNeighbor;
}
var rightEdge = potentialNeighbor.GetWorldVerts(potentialNeighbor.GetEdgeVerts(EdgeType.Right));
if (rightEdge.All(v => edgeVerts.Contains(v)))
{
return potentialNeighbor;
}
}
}
if (level > 0)
{
// if we made it this far we haven't found a neighbor yet so try 1 level lower Quads
potentialNeighbors = Quads[level - 1].Where(n => n != quad.GetParent()).ToList();
if (potentialNeighbors.Any())
{
foreach (Quad potentialNeighbor in potentialNeighbors)
{
var topEdge = potentialNeighbor.GetWorldVerts(potentialNeighbor.GetEdgeVerts(EdgeType.Top));
if (topEdge.Any(v => edgeVerts.Contains(v)))
{
return potentialNeighbor;
}
var bottomEdge = potentialNeighbor.GetWorldVerts(potentialNeighbor.GetEdgeVerts(EdgeType.Bottom));
if (bottomEdge.Any(v => edgeVerts.Contains(v)))
{
return potentialNeighbor;
}
var leftEdge = potentialNeighbor.GetWorldVerts(potentialNeighbor.GetEdgeVerts(EdgeType.Left));
if (leftEdge.Any(v => edgeVerts.Contains(v)))
{
return potentialNeighbor;
}
var rightEdge = potentialNeighbor.GetWorldVerts(potentialNeighbor.GetEdgeVerts(EdgeType.Right));
if (rightEdge.Any(v => edgeVerts.Contains(v)))
{
return potentialNeighbor;
}
}
}
}
return null;
}
有没有人有这方面的经验并愿意分享一些其他优化查找的方法?提前致谢。
【问题讨论】: