【发布时间】:2021-04-05 22:31:18
【问题描述】:
我已阅读 this 关于正确加载纹理坐标的帖子,一切正常,但问题在于速度。
基本上,这个想法是寻找一个先前处理过的顶点,它可能具有与当前正在处理的顶点完全相同的属性值,如果存在这样的顶点,则将该顶点索引值用于您的 indexBuffer 并继续。非常简单的概念和实现,这就是我的做法
class Vertex
{
//The index values read from a file either by processing the f attribute in obj files or the <p> attribute for meshes in colladae files
private final int
vertexIndex,
texCoordIndex,
normalIndex,
colorIndex;
//The actual values for each attribute used in the mesh
private final Vector3f
vertex=new Vector3f(),
normal=new Vector3f(),
color=new Vector3f();
private final Vector2f texCoord=new Vector2f();
@Override
public boolean equals(Object obj)//The key method used for finding duplicate vertices from the list
{
Vertex v=(Vertex)obj;
//Check if every attribute of both are same
return this.vertexIndex==v.VertexIndex
&& this.texCoordIndex==v.texCoordIndex
&& this.normalIndex==v.normalIndex
&& this.colorIndex==v.colorIndex;
}
}
最后我们有一个数组列表
ArrayList<Vertex> vertices=new ArrayList();
对于从文件中读取的每个顶点,这个想法很简单
Vertex newVertex=readFromFile();
int prev=vertices.indexOf(newVertex);
if(prev!=-1)//We have found an similar vertex from before so use that
{
indexBuffer.add(prev); //the indexBuffer will use the vertex at that position
}
else
{
vertices.add(newVertex); //Add new vertex
indexBuffer.add(vertices.size()-1);//New Vertex Index is simply the index of last element in the list
}
虽然这会产生正确的结果,但问题在于性能,因为对于添加的每个第 n 个顶点,我们都必须执行“线性搜索!!!”在之前添加的 n-1 个顶点上找到我们的重复顶点,这很糟糕,因为我花了 7 秒来加载 Standford 龙模型,但如果我完全放弃查找过程并只使用重复项,则只需 1.5 秒。
我想到的一个优化是因为我使用 java 是利用 java 14 的并行流的力量来寻找这样的重复。
Optional<Vertex> possibleDuplicate=vertices.stream()
.parallel()
.filter(prev->prev.equals(newVertex))
.findFirst();
但这是一个更糟糕的想法,因为我现在需要 12 秒才能加载。一个可能的原因可能是为每个要处理的 newVertex 生成 100 个线程是一个巨大的开销。
他在帖子中提到,他在已排序的顶点上使用二进制搜索来更快地查找重复项,但对此有一些疑问
当顶点有多个属性时,我根据什么属性对顶点进行排序?
对 ArrayList 进行二分搜索的一种方法是使用内置的 collections 框架,但我如何告诉比较器一个顶点是否小于 还是比其他的更大?
对于大型模型,它变得如此缓慢,我不得不让用户选择使用标志消除重复。
有没有更好的办法?
【问题讨论】:
标签: java duplicates vertex