我已经使用四叉树在我的图形引擎中实现了基本地形,现在我遇到了修复T型接头和裂缝的问题。首先我使用的是OpenGL 3.2,所以我无法使用tesslation。也许我会在不久的将来实现这个功能。基本上我有一个存储四叉树对象的terrain对象,并有一个名为render的方法:
/**
* Render tile
* @param program - shader program
*/
public void render(Camera camera, Shader program)
{
if(camera.hasMoved())
this.quadtree.updateQuadTree(camera);
this.quadtree.render(program);
}
然后我的四叉树对象有四个名为TerrainTreeNode的孩子,这个方法:
/**
* Update quadtree
* @param camera - camera
*/
public void updateQuadTree(Camera camera)
{
for(Node node : getChildren())
((TerrainTreeNode) node).updateQuadtree(camera);
}
然后我的TerrainTreeNode对象有以下方法:
/**
* Update quad tree
* @param camera - camera
*/
public void updateQuadtree(Camera camera)
{
updateChildNodes(camera.position);
for(Node node : getChildren())
{
((TerrainTreeNode) node).updateQuadtree(camera);
}
}
/**
* Update child nodes
* @param cameraPosition - camera position
*/
private void updateChildNodes(Vector3f cameraPosition)
{
Vector3f tempCamera = new Vector3f(cameraPosition);
Vector3f tempPosition = new Vector3f(this.position);
Vector3f.sub(tempCamera, tempPosition, tempCamera);
float distance = tempCamera.length();
switch(this.lod)
{
case 0:
if(distance < 1750)
{
addChildNodes(this.lod+1);
}
else if(distance >= 1750)
{
removeChildNodes();
}
break;
case 1:
if(distance < 874)
{
addChildNodes(this.lod+1);
}
else if(distance >= 874)
{
removeChildNodes();
}
break;
case 2:
if(distance < 386)
{
addChildNodes(this.lod+1);
}
else if(distance >= 386)
{
removeChildNodes();
}
break;
case 3:
if (distance < 192)
{
addChildNodes(this.lod+1);
}
else if(distance >= 192)
{
removeChildNodes();
}
break;
case 4:
if(distance < 100)
{
addChildNodes(this.lod+1);
}
else if(distance >= 100)
{
removeChildNodes();
}
break;
case 5:
if(distance < 50)
{
addChildNodes(this.lod+1);
}
else if(distance >= 50)
{
removeChildNodes();
}
break;
case 6:
if(distance < 0)
{
addChildNodes(this.lod+1);
}
else if(distance >= 0)
{
removeChildNodes();
}
break;
case 7:
if (distance < 0)
{
addChildNodes(this.lod+1);
}
else if(distance >= 0)
{
removeChildNodes();
}
break;
}
}
/**
* Add child nodes
* @param lod - level of detail
*/
public void addChildNodes(int newLod)
{
if(isLeaf)
{
isLeaf = false;
if(this.mesh != null)
this.mesh.dispose();
}
if(getChildren().size() == 0)
{
float newWidth = this.width/2f;
float newWidth2 = newWidth/2f;
for(int i = 0; i < 2; i++)
{
for(int j = 0; j < 2; j++)
{
float first, second;
if(i == 0)
first = -(newWidth/2f);
else
first = newWidth/2f;
if(j == 0)
second = -(newWidth/2f);
else
second = newWidth/2f;
Vector3f newPosition = new Vector3f(this.position.x+first,
0f, this.position.z+second);
addChild(new TerrainTreeNode(newPosition,
newLod,
new Vector2f(i, j),
newWidth));
}
}
}
}
/**
* Remove child nodes
*/
private void removeChildNodes()
{
if(!isLeaf)
{
isLeaf = true;
this.mesh = generateMesh();
}
//Remove childrends
if(getChildren().size() != 0)
{
for(Node child : getChildren())
child.dispose();
getChildren().clear();
}
}
正如你所看到的那样,树节点距离摄像机的距离很远,然后它会删除子节点并创建自己的vao,相反,它会创建子节点并从内存中删除vao。我的vao使用三角扇,它看起来像这样:
1,2,4,6,8和10个顶点始终处于活动状态,其他我要打开和关闭的顶点取决于邻居的详细程度以避免这种情况:
算法应该禁用红色顶点。我怎样才能做到这一点?如何找到所有无用的顶点? 该算法基于来自gamesutra的这篇文章。
感谢您的帮助!
修改 我发现(从这个链接:http://www.dice.se/wp-content/uploads/2014/12/Chapter5-Andersson-Terrain_Rendering_in_Frostbite.pdf - &gt;请参阅第53-55页)我不必打开和关闭顶点,而是我必须在不同的vao中存储节点的所有排列。这很清楚。但仍然不知道如何检测裂缝:/。
答案 0 :(得分:1)
我不想在你的情况下修改数据,四叉树。
我更喜欢根据LOD选择要绘制的子节点和节点。当相机很远时,只有大多数孩子被丢弃(他们在屏幕上的尺寸远小于一个像素),许多人只选择点'1'或连接中的一些(2,4,6或8),并且只有最接近所有的vetices。
您需要确定哪个顶点是每个LOD的“相关”。
您应该使用“选择子节点”部分。
您需要的是一种为贴片选择顶点的方法,使其适合距离相机较远的相邻贴片。因此,该邻居使用不同的LOD。
算法取决于邻居的相对位置(左侧或右侧或上下)。它还取决于邻居与补丁相比的不同LOD(如果使用多个LOD,从补丁到其邻居的LOD步骤应该只有一个,但是要小心,你可以编写高低LOD之间的连接,而不是中途LOD)。有几种组合。
要允许至少两个不同的LOD,您需要一个5x5顶点补丁。低LOD补丁将是3x3(你画的是什么)。
然后你选择高LOD的顶点(你称之为“修改qtree”,右边?),如下所示:
func1_list = func1(x)
具有低LOD的邻居选择其所有顶点。
通过使用索引缓冲区选择顶点时,该链接中显示的内容。每个排列代表根据邻居的位置得到的顶点。