10.5 查询地形高度

要保证场景中的所有物体都保持在地面之上,你应该能够查询到任何位置的高度,并将物体放置在地面之上。你可以从高度图获取顶点高度,并从顶点中计算任何位置的高度。

要查询任意位置的高度,首先需要计算对应网格顶点的位置,你可以通过从原始地形位置减去查询位置获得顶点位置,但注意必须考虑地形的变换。然后你需要知道查询的是哪个地形网格,你可以通过将位置(相对于地形)除以blockScale得到。

图10-11显示了一个在位置(52, 48)上的物体,它在网格(1, 1)上。注意你没有考虑物体的Y坐标(表示物体的高度),这是因为地形是处在XZ平面上的,你查询的数值与XZ坐标联系。

图10-11

图10-11:与地形网格对应的物体位置

计算在地形网格上的物体位置的代码如下:

// Get the position relative to the terrain grid 
Vector2 positionInGrid = new Vector2( positionX - (StartPosition.X + Transformation.Translate.X), positionZ - 
(StartPosition.Y + Transformation.Translate.Z)); 

// Calculate the grid position 
Vector2 blockPosition = new Vector2( (int)(positionInGrid.X / blockScale), (int)(positionInGrid.Y / blockScale)); 

在计算了处在网格的哪个方块后,你还要计算处在哪个三角形中。你可以计算块中的物体位置的X坐标是否大于Z坐标。如果X坐标大于Z坐标,物体处于上面的三角形中,反之则在下面的三角形中,如图10-12所示:

图10-12

图10-2:地形网格中的块。如果X坐标大于Z坐标,物体处于上面的三角形中,反之则在下面的三角形中 在找到物体处在哪个三角形后,你可以通过顶点高度的插值获取三角形内部的位置高度。在GetHeight方法中使用如下代码计算地形位置的高度:

private float GetHeight(float positionX, float positionZ) 
{ 
    float height = 	-999999.0f; 
    if (heightmap == null) 
        return height; 
    // Get the position relative to the terrain grid 
    Vector2 positionInGrid = new Vector2( positionX -(StartPosition.X + Transformation.Translate.X),
     positionZ - (StartPosition.Y + Transformation.Translate.Z));
     
     // Calculate the grid position Vector2 
     blockPosition = new Vector2( (int)(positionInGrid.X / blockScale), (int)(positionInGrid.Y / blockScale)); 
     
     // Check if the object is inside the grid 
     if (blockPosition.X >= 0 && blockPosition.X < (vertexCountX - 1) && 
			blockPosition.Y >= 0 && blockPosition.Y < (vertexCountZ - 1)) 
	{ 
	    Vector2 blockOffset = new Vector2( blockPosition.X - (int)blockPosition.X, 
			blockPosition.Y - (int)blockPosition.Y); 
			
	    // Get the height of the four vertices of the grid block 
	    int vertexIndex = (int)blockPosition.X + (int)blockPosition.Y 	* vertexCountX; 
	    float height1 = heightmap[vertexIndex + 1]; 
	    float height2 = heightmap[vertexIndex]; 
	    float height3 = heightmap[vertexIndex + vertexCountX +	1];
	    float height4 = heightmap[vertexIndex + vertexCountX]; 
	    
	    // Top triangle float heightIncX, heightIncY; 
	    if (blockOffset.X > blockOffset.Y) 
	    {
	        heightIncX = height1 - height2; 
	        heightIncY = height3 - height1; 
	    } 
	    
	    // Bottom triangle 
	    else 
	    {
	        heightIncX = height3 - height4;
	        heightIncY = height4 - height2;
	    }
	    
	    // Linear 	interpolation to find the height inside the triangle
	    float lerpHeight = height2 + heightIncX * blockOffset.X + heightIncY * blockOffset.Y;
	    height = lerpHeight * heightScale;
	} 
	return height;
} 

注意使用这个方法只能保证场景中的所有物体在地面之上,要实现物体与地面之间真实的互动,你必须实现一个物理系统。


发布时间:2009/4/24 上午11:59:25  阅读次数:5650

2006 - 2024,推荐分辨率 1024*768 以上,推荐浏览器 Chrome、Edge 等现代浏览器,截止 2021 年 12 月 5 日的访问次数:1872 万 9823 站长邮箱

沪 ICP 备 18037240 号-1

沪公网安备 31011002002865 号