使用高度图生成地形

来源:互联网 发布:梦幻古龙登录器源码 编辑:程序博客网 时间:2024/05/29 15:15

 第7章01节 地形处理

感觉上地形处理技术应该不会少.这里用的是高度图,简单的说就是用位图上的一个象素表示一个顶点,用象素的亮度表示顶点的高度.

 

///首先是获取高度图纹理的信息,,在这里有用的就是长度和宽度

 D3DSURFACE_DESC  ddsd; 

 g_pTexHeight->GetLevelDesc( 0, &ddsd ); /// 纹理信息
 g_cxHeight = ddsd.Width;    /// 纹理的长度
 g_czHeight = ddsd.Height;    /// 纹理的宽度

 

///纹理存储器
D3DLOCKED_RECT  d3drc;

 g_pTexHeight->LockRect( 0, &d3drc, NULL, D3DLOCK_READONLY );//
    VOID* pVertices;

    if( FAILED( g_pVB->Lock( 0, g_cxHeight*g_czHeight*sizeof(CUSTOMVERTEX), (void**)&pVertices, 0 ) ) )///顶点缓冲,接收数据
        return E_FAIL;

 CUSTOMVERTEX v;
 CUSTOMVERTEX* pV = (CUSTOMVERTEX*)pVertices;
 for( DWORD z = 0 ; z < g_czHeight ; z++ )
 {
  for( DWORD x = 0 ; x < g_cxHeight ; x++ )
  {
   v.p.x = (float)x-g_cxHeight/2.0f;  /// 顶点的x坐标(以原点为准对齐网格)
   v.p.z = -((float)z-g_czHeight/2.0f); /// 顶点的z坐标(以顶点为准对齐网格),z轴指向显示器,乘以“-”.
   v.p.y = ((float)(*((LPDWORD)d3drc.pBits+x+z*(d3drc.Pitch/4))&0x000000ff))/10.0f; /// 由于是DWORD,因此为pitch/4
   v.n.x = v.p.x;
   v.n.y = v.p.y;
   v.n.z = v.p.z;
   D3DXVec3Normalize( &v.n, &v.n );
   v.t.x = (float)x / (g_cxHeight-1);
   v.t.y = (float)z / (g_czHeight-1);
   *pV++ = v;
   //g_pLog->Log( "[%f,%f,%f]", v.p.x, v.p.y, v.p.z );
  }
 }

    g_pVB->Unlock();
 g_pTexHeight->UnlockRect( 0 );

为了让生成的地形是以原点为中心的,,所以x,y分别减去了高度图长度和宽度的一半.

接下来v.p.y = ((float)(*((LPDWORD)d3drc.pBits+x+z*(d3drc.Pitch/4))&0x000000ff))/10.0f; 这句就是设置顶点高度,算是全篇核心.在这里纹理存储器相当于一个矩阵,矩阵的[0,0]单元存储位置是用d3drc.pBits来指示的,假设它的列数是P,那么[x,z]单元的存储位置就是d3drc.pBits+x+z*P.而在纹理存储结构中,用d3drc.Pitch来表示列数,并且是按byte数的,也就是说,对于一张128象素宽的图片,它每个象素有32位,即4bytes,那么在纹理存储结构中,d3drc.Pithc=128*4.这就是为什么代码中要除4了.

找到象素的存储位置后,前面加*号,取其内容,与0x000000ff进行按位与运算,由于灰度图片中r,g,b值都是相同的,所以只需要取最低的8位就可以表示象素的明暗,,也就可以表示顶点的高低了.

 

 if( FAILED( g_pIB->Lock( 0, (g_cxHeight-1)*(g_czHeight-1)*2 * sizeof(MYINDEX), (void**)&pI, 0 ) ) )
        return E_FAIL;

 for( DWORD z = 0 ; z < g_czHeight-1 ; z++ )
 {
  for( DWORD x = 0 ; x < g_cxHeight-1 ; x++ )
  {
   i._0 = (z*g_cxHeight+x);
   i._1 = (z*g_cxHeight+x+1);
   i._2 = ((z+1)*g_cxHeight+x);
   *pI++ = i;
   i._0 = ((z+1)*g_cxHeight+x);
   i._1 = (z*g_cxHeight+x+1);
   i._2 = ((z+1)*g_cxHeight+x+1);
   *pI++ = i;
  }
 }
    g_pIB->Unlock();

最后这段填充索引缓冲,索引个数为(g_cxHeight-1)*(g_czHeight-1)*2,这是因为x,z方向分别有了g_cxHeight和g_czHeight个顶点,那么一共可以生成(g_cxHeight-1)*(g_czHeight-1)个四边形,而每个四边形由左上角和右下角两个三角形组成,所以再乘2

原创粉丝点击