10.5 查询地形高度
要保证场景中的所有物体都保持在地面之上,你应该能够查询到任何位置的高度,并将物体放置在地面之上。你可以从高度图获取顶点高度,并从顶点中计算任何位置的高度。
要查询任意位置的高度,首先需要计算对应网格顶点的位置,你可以通过从原始地形位置减去查询位置获得顶点位置,但注意必须考虑地形的变换。然后你需要知道查询的是哪个地形网格,你可以通过将位置(相对于地形)除以blockScale得到。
图10-11显示了一个在位置(52, 48)上的物体,它在网格(1, 1)上。注意你没有考虑物体的Y坐标(表示物体的高度),这是因为地形是处在XZ平面上的,你查询的数值与XZ坐标联系。
图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-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 阅读次数:5582