在stage3D中使用高度图来绘制地形

本文已抄送到天地会 : http://bbs.9ria.com/thread-192787-1-1.html

这是效果图
terrain

首先先准备一张高度图
heightMap
你可以用Photoshop制作,在创建图片的时候就选择灰度图. 当你制作完毕一张灰度图的时候,保存的格式最好是8Bit的RAW文件,这样每个像素都被保存在 unsignedbyte 中,且没有各种烦人的文件头信息.有且只有像素信息.

为了方便测试,在AS中我们将这个RAW文件嵌入到项目中,用下面代码

[cc lang=”actionscript3″]
[Embed(source=”../../source/coastMountain64.raw”,mimeType = “application/octet-stream”)]
private var terrainData : Class;
[/cc]

当文件嵌入后,我们就开始着手解析了.解析的方法很简单,按顺序读取字节流,然后存进一个 Vector. 数组中.

[cc lang=”actionscript3″]
private function parseHeightMaps(data : ByteArray) : Boolean
{
if(null == data || 0 == data.bytesAvailable) return false;

var len : uint = data.bytesAvailable;
for(var i : int = 0; i < len; i++){ m_heightMap.push(data.readUnsignedByte()); } return true; } [/cc] 现在我们有了地形的数据了,为了让其显示出来,我们开始创建顶点和索引 顶点的格式是 [x,y,z,u,v] 5个数据 如果每个顶点之间是紧密排列的话,其中u,v的递增量可以通过下面的方式计算出. [cc lang="actionscript3"] var uCoordIncrementSize : Number = 1.0 / 每列顶点数; var vCoordIncrementSize : Number = 1.0 / 每行顶点数; [/cc] 由于高度图是 64 * 64 的大小,我们做 64 * 64的循环来取顶点 startZ = 0, endZ = 63; startX = 0, endX = 63; 如果顶点间是紧密排列的. 那么 m_cellSpacing 为1.0 [cc lang="actionscript3"] for(z = startZ; z >= endZ; z -= m_cellSpacing)
{
j = 0;
for(x = startX; x <= endX; x += m_cellSpacing) { //计算当前顶点缓冲的索引,避免死循环 var index : int = i * m_numVertsPerRow + j; m_rawVertex.push(x,m_heightMap[index],z,j * uCoordIncrementSize,i * vCoordIncrementSize); j++; } i++; } [/cc] 解析完顶点后,就要开始计算索引了. indexbuffer

通过这张图,可以理解到,2个三角形和顶点数组中索引对应的上下两行的关系.
当前顶点的 index, index + 1 和下一行的 index 构成第一个三角形, 另一半三角形也同样. 他们共用 C 顶点.
转换成代码就是如下的形式
[cc lang=”actionscript3″]
private function computeIndices() : void
{
var baseIndex : int = 0;

for(var i : int = 0; i < m_numCellsperCol; i++) { for(var j : int = 0; j < m_numCellsPerRow; j++) { m_rawIndex[baseIndex] = i * m_numVertsPerRow + j; m_rawIndex[baseIndex + 1] = i * m_numVertsPerRow + j + 1; m_rawIndex[baseIndex + 2] = (i + 1) * m_numVertsPerRow + j; m_rawIndex[baseIndex + 3] = (i + 1) * m_numVertsPerRow + j; m_rawIndex[baseIndex + 4] = i * m_numVertsPerRow + j + 1; m_rawIndex[baseIndex + 5] = (i + 1) * m_numVertsPerRow + j + 1; baseIndex += 6; } } trace("索引解析完毕"); } [/cc] 现在我们有了顶点,也有了索引.就可以将其显示出来了. 贴图什么随便设定就好了. demo is here

你可能会觉得地形很难看出高低的感觉,这是因为没有地形没有阴影,当然这是下一篇进阶的功能了.

发表评论

电子邮件地址不会被公开。 必填项已用*标注