看了OpenGL编3D游戏_CAI,里面的那个A05_开天辟地的例子不大明白,地图的那个部分
void baiscobj::InitTerrain(float h)  //初始地形
{ int index = 0;
  int Vertex;
  for (int z = 0; z < MAP_W; z++)
   for (int x = 0; x < MAP_W; x++)
    { Vertex = z * MAP_W + x;
      g_terrain [Vertex][0] = float(x)*MAP_SCALE;
      g_terrain [Vertex][1] = (float)(g_imageData[(z*MAP_W+x)*3]/3);
      g_terrain [Vertex][2] = -float(z)*MAP_SCALE;
      g_texcoord[Vertex][0] = (float) x;
     g_texcoord[Vertex][1] = (float) z; 
     g_index [index++] = Vertex;
     g_index [index++] = Vertex+ MAP_W;
   }
  glEnableClientState(GL_VERTEX_ARRAY); 
  glVertexPointer    (3,GL_FLOAT,0,g_terrain);
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  glTexCoordPointer  (2,GL_FLOAT,0,g_texcoord);
}
void baiscobj::DrawSand()
{ glBindTexture(GL_TEXTURE_2D, g_cactus[0]);
  glTexEnvf    (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  for (int z = 0; z < MAP_W-1; z++)
    glDrawElements(GL_TRIANGLE_STRIP,MAP_W*2,GL_UNSIGNED_INT,&g_index[z*MAP_W*2]);
}
float baiscobj::GetHeight(float x, float z)   //获取高度
{  float CameraX = x/MAP_SCALE;
float CameraZ =-z/MAP_SCALE;  
int Col0 = int(CameraX);  
int Row0 = int(CameraZ);
int Col1 = Col0 + 1;
int Row1 = Row0 + 1; 
if (Col1 > MAP_W) Col1 = 0;
if (Row1 > MAP_W) Row1 = 0;
float h00=g_terrain[Col0 + Row0*MAP_W][1];
float h01=g_terrain[Col1 + Row0*MAP_W][1];
float h11=g_terrain[Col1 + Row1*MAP_W][1];
float h10=g_terrain[Col0 + Row1*MAP_W][1];
float tx =CameraX - int(CameraX);
float ty =CameraZ - int(CameraZ);
float txty = tx * ty;
return h00*(1.0f-ty-tx+txty) 
+ h01*(tx-txty)
+ h11*txty
+ h10*(ty-txty); 
}
有朋友能详细解释一下吗,看了好久,没看明白,

解决方案 »

  1.   

    void baiscobj::InitTerrain(float h)  //初始地形 

      int index = 0; 
      int Vertex; 
      for (int z = 0; z < MAP_W; z++) 
      for (int x = 0; x < MAP_W; x++) 
        { Vertex = z * MAP_W + x; 
          g_terrain [Vertex][0] = float(x)*MAP_SCALE; 
          g_terrain [Vertex][1] = (float)(g_imageData[(z*MAP_W+x)*3]/3); 
          g_terrain [Vertex][2] = -float(z)*MAP_SCALE; 
          g_texcoord[Vertex][0] = (float) x; 
        g_texcoord[Vertex][1] = (float) z; 
        g_index [index++] = Vertex; 
        g_index [index++] = Vertex+ MAP_W; 
      } 
     
      glEnableClientState(GL_VERTEX_ARRAY); 
      glVertexPointer    (3,GL_FLOAT,0,g_terrain); 
      glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
      glTexCoordPointer  (2,GL_FLOAT,0,g_texcoord); 
    } void baiscobj::DrawSand() 
    { glBindTexture(GL_TEXTURE_2D, g_cactus[0]); 
      glTexEnvf    (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 
      glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); 
      for (int z = 0; z < MAP_W-1; z++) 
        glDrawElements(GL_TRIANGLE_STRIP,MAP_W*2,GL_UNSIGNED_INT,&g_index[z*MAP_W*2]); 

    float baiscobj::GetHeight(float x, float z)  //获取高度 
    {  float CameraX = x/MAP_SCALE; 
       float CameraZ =-z/MAP_SCALE;  
       int Col0 = int(CameraX);  
       int Row0 = int(CameraZ); 
       int Col1 = Col0 + 1; 
       int Row1 = Row0 + 1; 
       
       if (Col1 > MAP_W) Col1 = 0; 
       if (Row1 > MAP_W) Row1 = 0; 
       
       float h00=g_terrain[Col0 + Row0*MAP_W][1]; 
       float h01=g_terrain[Col1 + Row0*MAP_W][1]; 
       float h11=g_terrain[Col1 + Row1*MAP_W][1]; 
       float h10=g_terrain[Col0 + Row1*MAP_W][1]; 
       float tx =CameraX - int(CameraX); 
       float ty =CameraZ - int(CameraZ); 
       float txty = tx * ty; 
       
       return h00*(1.0f-ty-tx+txty) + h01*(tx-txty) + h11*txty + h10*(ty-txty); 
    } 把代码调整了一下,衷心向各位请教
      

  2.   

    InitTerrain函数构造地形,g_terrain 数组用来存放实际地形坐标,g_texcoord用来存放纹理坐标,而g_index 存放的是顶点的索引。这样处理是为了使用项点数组来渲染地形,使用顶点数组可大大提高渲染效率。
      glEnableClientState(GL_VERTEX_ARRAY); 
      glVertexPointer    (3,GL_FLOAT,0,g_terrain); 
      glEnableClientState(GL_TEXTURE_COORD_ARRAY); 
      glTexCoordPointer  (2,GL_FLOAT,0,g_texcoord); 
    这几句启用了顶点数组,包括坐标和纹理,并指定了顶点数组,分别是g_terrain和g_texcoord
    glDrawElements(GL_TRIANGLE_STRIP,MAP_W*2,GL_UNSIGNED_INT,&g_index[z*MAP_W*2])这一句进行渲染,注意它最后一个参数是g_index,表示顶点的索引。g_terrain [Vertex][0] = float(x)*MAP_SCALE; 
    g_terrain [Vertex][1] = (float)(g_imageData[(z*MAP_W+x)*3]/3); 
    g_terrain [Vertex][2] = -float(z)*MAP_SCALE; 
    这三句是构造地形,g_terrain [Vertex][1] 表示的是地面的高度。GetHeight(float x, float z)这个函数是获取指定地点的高度,
    h00*(1.0f-ty-tx+txty) + h01*(tx-txty) + h11*txty + h10*(ty-txty)是进行双线性插值,这样即便X,Z不是三角形顶点也可以得到高度值。
      

  3.   

    谢谢4楼的朋友,我刚刚接触Opengl,还是小菜,问题比较多,见谅,呵呵
        
      g_terrain [Vertex][1] = (float)(g_imageData[(z*MAP_W+x)*3]/3); //这个高度值是怎么获得的,尤其是这句话(z*MAP_W+x)*3],能解释下么?另外 建立g_index存放顶点索引有什么作用吗?什么是双线性插值?
      

  4.   

    这个文件里面有个LoadBit函数,它用来读取一个位图,这个位图里面存的就是地面的高度信息,这就是所谓的“高度图”。g_imageData存放的正是从这个位图里面读取的高度信息,而(z*MAP_W+x)*3是相应网格点所对应的索引值。你可以去看一下关于高度图的资料。使用顶点索引可以提高效率,比如说有一个立方体,它有六个面,八个顶点,这八个顶点的坐标可以用一个数组表示
    {V0,V1,V2,V3....,V7},而立方体的六个面可以用顶点的索引号来组成,比如说假设上表面由V0,V1,V2,V3这四个点组成,下表面由V4,V5,V6,V7组成,则上表面可以用数组{0,1,2,3}表示,下表面用(4,5,6,7}表示,索引数组中元素分别表示对应点在顶点数组中的索引号,由于三维坐标数据比较大,用索引数组只需构造指向数据的索引,节省了空间。对于一个目的像素,设置坐标通过反向变换得到的浮点坐标为(i+u,j+v),其中i、j均为非负整数,u、v为[0,1)区间的浮点数,则这个像素得值 f(i+u,j+v) 可由原图像中坐标为 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定,即:
        f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
    其中f(i,j)表示源图像(i,j)处的的像素值,以此类推
      这就是双线性内插值法。
      

  5.   

    (g_imageData[(z*MAP_W+x)*3]/3);
    这里使用的地图是bmp格式的,所以有三个分量,作者只选择了第一个分量值作为地图高度,也就是g_imageData[(z*MAP_W+x)*3],其实也可以选择另外的分量:g_imageData[(z*MAP_W+x)*3+1]或者g_imageData[(z*MAP_W+x)*3+2]至于为什么要除以3,你可以看看这个函数有个参数float h,所以我认为作者本来是要除以h的,从而通过参数控制地形高度,也就是:g_imageData[(z*MAP_W+x)*3]/h对于获取指定坐标的高度GetHeight函数,我也在研究,希望有高手指教!
      

  6.   

    如何用OpenGL显示类似于山坡的地形,就是节节升高的!