Silverlight C# 游戏开发:L7 HeightMap

Silverlight C# 游戏开发:L7 HeightMap,第1张

概述在3D游戏中,我们经常能够看到连绵起伏的山脉,当在夕阳西下一览众山之时,可曾想过这美景在3D世界中是如何呈现,前面讲完了灯光和摄像机,本篇聊聊Silverlight3D游戏的HeightMap,并从文件中取得高度图信息形成下面的3D地形。   HeightMap是地形的输入数据,可以理解为位图,一个2D矩阵,和位图不同的是,把元素的颜色值映射为高度值,现实中的地形是真实的,不是由三角平面模拟的,但

在3D游戏中,我们经常能够看到连绵起伏的山脉,当在夕阳西下一览众山之时,可曾想过这美景在3D世界中是如何呈现,前面讲完了灯光和摄像机,本篇聊聊Silverlight3D游戏的Heightmap,并从文件中取得高度图信息形成下面的3D地形。

 

Heightmap是地形的输入数据,可以理解为位图,一个2D矩阵,和位图不同的是,把元素的颜色值映射为高度值,现实中的地形是真实的,不是由三角平面模拟的,但是3D图形图像处理中常常使用三角形来代替地形的表面,每个三角形的顶点高度在山脉到山谷之间转换,模拟自然地形。我们来看看Heightmap的原理:

 

使用Heightmap的原因是表示方便,存储和修改容易,从数据的角度上,Heightmap一般是灰度图,灰度图的一个像素数据只需要0xFF一个字节就可以表示,如果变成三维坐标,基本数据值类型就会变得大,不利于数据处理,同样一些阻挡算法也可以通过Heightmap计算,这部分我相信专门研究3D算法的朋友有研究,在这里就不做多讲。形成Heightmap的算法也比较简单,只是将顶点集合做好即可。

那么在Balder 3D中如何实现Heightmap,在Balder.Objects.GeometrIEs中提供了Heightmap类,可以通过简单的设置就能到Heightmap

  Heightmap heightmap = new Heightmap();      heightmap.Dimension = new Dimension() { WIDth = 120,Height = 120 };      heightmap.LengthSegments = 16;      heightmap.HeightSegments = 16;      game.Children.Add(heightmap);                
Dimension属性是表示的大小;

LengthSegments属性是横向面片数量

HeightSegments属性是纵向面片数量

那么横纵相乘就是16*16 = 256面片,依据个人所需要的平滑度可以进行调整。

HeightmapArray属性是高位数据,用float类型表示,它达标了在Heightmap区域内的高位信息,这个数组可大可小,越大精度越高,越小精度越小,下面简单生成一个数组看看实际的效果,代码如下

  float[,] HeightmapArray = new float[5, 5]          {              {0,5,10,0},             {0,20,             {0,30,0}          };                
这是一个[5,5]的float数组,对其进行了简单的数据填充,将这个数组赋值给HeightmapArray属性,就可以得到下面的这个运行效果:

 

对照前面的实现原理,是否有意思了呢,这个数组的构建可以依据自己的需求做修改和开发,为了满足想进阶的朋友,我下面写了一个从位图中创建Heightmap例子,以作参考。

  //从位图中创建高度图      voID CreateHeightmapFormBitmap(Uri uri)      {                      BitmAPImage bitmap = new BitmAPImage();          //从资源中取得BitmapStream          StreamResourceInfo sri = Application.GetResourceStream(uri);          bitmap.SetSource(sri.Stream);          //生成WriteableBitmap          WriteableBitmap writeablebitmap = new WriteableBitmap(bitmap);          //创建高度图数组          float[,] HeightmapArray = new float[bitmap.PixelHeight,bitmap.PixelWIDth];          //将数组拷贝到高度图数组          for (int i = 0; i < bitmap.PixelHeight; i++)          {              for (int j = 0; j < bitmap.PixelWIDth; j++)              {                  int index = bitmap.PixelWIDth * i + j;                  int pixel = writeablebitmap.Pixels[index];                  byte[] bytes = BitConverter.GetBytes(pixel);                  //计算:颜色越深则越低,颜色月浅则越高,50是最高的高度值                  HeightmapArray[i,j] = ((float)(bytes[0] + bytes[1] + bytes[2]) / 3) / 255 * 50 ;              }          }          //赋值          heightmap.HeightmapArray = HeightmapArray;      }                
我使用了一个比较暴力的像素点取值算法,将R、G、B三值进行平均,就能得到一个近似的灰度数值,然后除以255,乘以50换算成以50为最高的高度数组,当然了,这里你可以依据要求从50修改成任何数字。关于图形图像的算法,及实现原理请参考 Silverlight C# 游戏开发:资源的处理,图像算法(二)

在这里使用了GetResourceStream资源读取的方式,因此你需要将位图引用到工程当中,下面是测试用高度位图,工程中做了缩小修改,毕竟用不上这么精细的位图。

 

使用上述代码实现即可,可以点击直接下载工程浏览和测试,那么运行的预览效果如下:

工程中如果缺少Balder.dll请在这里快速下载:SL4_Balder.rar

下一篇我们介绍材质的应用,如何对模型进行贴图和更换贴图,以及贴图的属性,同时可能还结合Heightmap依据地理信息制作真实地图,那么下次再见。

总结

以上是内存溢出为你收集整理的Silverlight C# 游戏开发:L7 HeightMap全部内容,希望文章能够帮你解决Silverlight C# 游戏开发:L7 HeightMap所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1075560.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-26
下一篇 2022-05-26

发表评论

登录后才能评论

评论列表(0条)

保存