opengl 高程地形类

作者在 2009-10-02 01:07:15 发布以下内容
   绘制3D地形图的程序经常使用灰度图存储地形图的数据。程序使用OPENGL或D3D引擎将其绘制出来。3D游戏引擎对地形处理是很有技巧的。如何高速处理又不失效果?这些方面的资料比较少看到。我写了一个简单的高程地形类,以后整合好资料再完善。有刚学的也来完善。
//-----------------------------------------------
//CMGTerrain.h
//作者:刘鑫
//E-MAIL:LIUXIN1984121@TOM.COM
//时间:2009,7,25
//说明CMGTerrain类用于生成地形
//-----------------------------------------------
#if !defined  (__CMGMAP_INCLUDED__)
#define __CMGMAP_INCLUDED__
#include <windows.h>
#include <gl/gl.h>           
#include <gl/glu.h>    
#include <gl/glaux.h> 
#include <stdio.h>
#include "glext.h"
#include "texture.h"

class CMGTerrain
{
public:
  CMGTerrain();
  CMGTerrain(float scale,float kheight,BOOL color);//scale地图X,Z比例.kheight高度比例,color是否使用颜色数组
  ~CMGTerrain();
  BOOL Create(char *mapdata_file);
  BOOL LoadTextures(char *mapture);
  BOOL Draw();
  float   GetHeight(float x, float z);
  BOOL SetUV(float m_u,float m_v);//设置纹理的插值密度
  BOOL LoadSkyTexture(char *filename,int n);
  BOOL DrawSky();
  CTexture  skyTexture[6];//天空纹理
  int MAP_X;      
  int MAP_Z;
  float MAP_SCALE;
private:
  void    InitializeTerrain();
  void    InitializeArrays();
  unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader);
  BITMAPINFOHEADER  g_bitmapInfoHeader;  
  unsigned char    *g_imageData; 
  CTexture m_terrainTex[5];   
  BOOL WritefloatBuf(float *buf,int row,int col,int maxw,float wbuf);
  float GetfloatBuf(float *buf,int row,int col,int maxw);

  float m_kheight;
  BOOL m_color;
  float m_U;//纹理X缩放
  float m_V;//纹理Z缩放
  float m_twidth;//纹理宽度
  float m_theight;//纹理长度
protected:
  GLuint *g_indexArray;
  float *g_terrain;
  float  *g_colorArray;
  float  *g_texcoordArray;
  PFNGLLOCKARRAYSEXTPROC    glLockArraysEXT;
  PFNGLUNLOCKARRAYSEXTPROC  glUnlockArraysEXT;
};
#endif
 
//-----------------------------------------------
//CMGTerrain.cpp
//作者:刘鑫
//E-MAIL:LIUXIN1984121@TOM.COM
//时间:2009,7,25
//说明CMGTerrain类用于生成地形
//-----------------------------------------------
#include "CMGTerrain.h"
CMGTerrain::CMGTerrain()
{
 MAP_SCALE=20.0f;
    glLockArraysEXT = 0;
    glUnlockArraysEXT = 0;
 MAP_X=0;      
    MAP_Z=0;
 m_kheight=1.0f;
 m_color=FALSE;
    m_t;//纹理宽度
    m_theight=0;//纹理长度
 m_U=1.0f;
 m_V=1.0f;
}
CMGTerrain::CMGTerrain(float scale,float kheight,BOOL color)
{
 m_color=color;
 MAP_SCALE=scale;
 MAP_X=0;      
 MAP_Z=0;
 m_kheight=kheight;
 m_t;//纹理宽度
 m_theight=0;//纹理长度
 m_U=1.0f;
 m_V=1.0f;
}
BOOL CMGTerrain::SetUV(float m_u,float m_v)
{
 m_U=m_u;
 m_V=m_v;
 return TRUE;
}
CMGTerrain::~CMGTerrain()
{
  free(g_imageData);
  delete []g_indexArray;
  delete []g_terrain;
  delete  []g_colorArray;
  delete  []g_texcoordArray;
}
BOOL CMGTerrain::Create(char *mapdata_file)
{
  g_imageData = LoadBitmapFile(mapdata_file, &g_bitmapInfoHeader);
  InitializeTerrain();
  InitializeArrays();
  char *extList = (char *) glGetString(GL_EXTENSIONS);
  if (extList && strstr(extList, "GL_EXT_compiled_vertex_array"))
  {
    glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC) wglGetProcAddress("glLockArraysEXT");
    glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC) wglGetProcAddress("glUnlockArraysEXT");
  }
  if (glLockArraysEXT)
    glLockArraysEXT(0, MAP_X * MAP_Z * 6);
  return TRUE;
}
BOOL CMGTerrain::WritefloatBuf(float *buf,int row,int col,int maxw,float wbuf)
{
  if((buf+maxw*row+col)!=NULL)
  {
    *(buf+maxw*row+col)=wbuf;
    return TRUE;
  }
  else
 return FALSE; 
}
float CMGTerrain::GetfloatBuf(float *buf,int row,int col,int maxw)
{
 float rebuf;
 rebuf=(*(buf+maxw*row+col));
 return rebuf;
}
void CMGTerrain::InitializeArrays()
{
  int index = 0;
  int currentVertex;
  float wbuf;
  float u_w;
  for (int z = 0; z < MAP_Z; z++)
  {
    for (int x = 0; x < MAP_X; x++)
    {
      currentVertex = z * MAP_X + x;
   wbuf=GetfloatBuf(g_terrain,x+MAP_X*z,1,3);
      wbuf=wbuf/255.0f;
   WritefloatBuf(g_colorArray,currentVertex,0,3,wbuf);
   WritefloatBuf(g_colorArray,currentVertex,1,3,wbuf);
   WritefloatBuf(g_colorArray,currentVertex,2,3,wbuf);
   u_w=(float)(MAP_X*MAP_SCALE*m_U)/m_twidth;
   wbuf=(float)x/(float)(MAP_X)*u_w;
      WritefloatBuf(g_texcoordArray,currentVertex,0,2,wbuf);
   wbuf=(float)z/(float)(MAP_X)*u_w;
      WritefloatBuf(g_texcoordArray,currentVertex,1,2,wbuf);
    }
  }
  for (z = 0; z < MAP_Z - 1; z++)
  {
    for (int x = 0; x < MAP_X; x++)
    {
      currentVertex = z * MAP_X + x;
      *(g_indexArray+index) = currentVertex + MAP_X;
   index++;
      *(g_indexArray+index) = currentVertex;
   index++;
    }
  }

  glEnableClientState(GL_VERTEX_ARRAY);
  glVertexPointer(3, GL_FLOAT, 0, g_terrain);
  if(m_color)
  {
    glEnableClientState(GL_COLOR_ARRAY);
    glColorPointer(3, GL_FLOAT, 0, g_colorArray);
  }
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
  glTexCoordPointer(2, GL_FLOAT, 0, g_texcoordArray);
}
void CMGTerrain::InitializeTerrain()
{
  for (int z = 0; z < MAP_Z; z++)
  {
    for (int x = 0; x < MAP_X; x++)
    {
   WritefloatBuf(g_terrain,x + MAP_X * z,0,3, float(x)*MAP_SCALE);
   WritefloatBuf(g_terrain,x + MAP_X * z,1,3,(float)g_imageData[(z*MAP_Z+x)*3]*m_kheight);
   WritefloatBuf(g_terrain,x + MAP_X * z,2,3,-float(z)*MAP_SCALE);      
    }
  }
}
unsigned char *CMGTerrain::LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{
  FILE *filePtr;                       
  BITMAPFILEHEADER  bitmapFileHeader; 
  unsigned char    *bitmapImage;       
  unsigned int      imageIdx = 0;      
  unsigned char     tempRGB;          
  int m_biwidth,m_biheight;
  filePtr = fopen(filename, "rb");
  if (filePtr == NULL)
    return NULL;

  fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);

  if (bitmapFileHeader.bfType != 0x4D42)
  {
    fclose(filePtr);
    return NULL;
  }

  fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);

  fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);

  if((bitmapInfoHeader->biSizeImage)==0)
  {
   MessageBox(NULL,"READ BMP ERROR", "InitializeTerrain",MB_ICONEXCLAMATION);
  }
  m_bi;biWidth;
  m_biheight=bitmapInfoHeader->biHeight;
 
  MAP_X=m_biwidth;
  MAP_Z=m_biheight;
  g_indexArray=new GLuint[MAP_X * MAP_Z * 6];
  g_terrain=new float[MAP_X * MAP_Z*3];
  g_colorArray=new float[MAP_X * MAP_Z*3];
  g_texcoordArray=new float[MAP_X * MAP_Z*2];

  bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);

  if (!bitmapImage)
  {
    free(bitmapImage);
    fclose(filePtr);
    return NULL;
  }

  fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);

  if (bitmapImage == NULL)
  {
    fclose(filePtr);
    return NULL;
  }

  for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx+=3)
  {
    tempRGB = bitmapImage[imageIdx];
    bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
    bitmapImage[imageIdx + 2] = tempRGB;
  }

  fclose(filePtr);
  return bitmapImage;
}
BOOL CMGTerrain::LoadTextures(char *mapture)
{
 m_terrainTex[0].LoadTexture(mapture);
 glGenTextures(1, &m_terrainTex[0].texID);
 glBindTexture(GL_TEXTURE_2D, m_terrainTex[0].texID);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //or GL_CLAMP
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //or GL_CLAMP
    m_theight=(float)m_terrainTex[0].height;
 m_t;
 switch (m_terrainTex[0].textureType)
 {
 case BMP:
  gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, m_terrainTex[0].width, m_terrainTex[0].height,
     GL_RGB, GL_UNSIGNED_BYTE, m_terrainTex[0].data);
  break;
 case PCX:
  gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, m_terrainTex[0].width, m_terrainTex[0].height,
     GL_RGBA, GL_UNSIGNED_BYTE, m_terrainTex[0].data);
  break;
 case TGA:
  gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, m_terrainTex[0].width, m_terrainTex[0].height,
     GL_RGB, GL_UNSIGNED_BYTE, m_terrainTex[0].data);
  break;
 default:
  break;
 }
   return TRUE;
}
BOOL CMGTerrain::Draw()
{
 int z=0;
 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 glEnable(GL_BLEND);
 glEnable(GL_ALPHA_TEST);
 glAlphaFunc(GL_GREATER,0.0);
 glDisable(GL_ALPHA_TEST);
 glEnable(GL_TEXTURE_2D);
 glBindTexture(GL_TEXTURE_2D, m_terrainTex[0].texID);
 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glPushMatrix();
  for (z = 0; z < MAP_Z-1; z++)
  {
    glDrawElements(GL_TRIANGLE_STRIP, MAP_X * 2, GL_UNSIGNED_INT, &g_indexArray[z * MAP_X * 2]);
  }
  glPopMatrix();
 int WORLD_SIZE;
    WORLD_SIZE=MAP_X*MAP_SCALE;
  DrawSky();     // 天空盒
  return TRUE;
}
 
BOOL CMGTerrain::DrawSky()
{
 
 int WORLD_SIZE;
    WORLD_SIZE=MAP_X*MAP_SCALE;
 
 glColor4f(1.0, 1.0, 1.0,1.0f);
 glPushMatrix();
 glTranslatef(WORLD_SIZE/2,WORLD_SIZE/2,-WORLD_SIZE/2);
 glScalef(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE);
 
 float cz = -0.0f,cx = 1.0f;
 float r = 1.0f; 
 glBindTexture(GL_TEXTURE_2D,skyTexture[0].texID);
 glBegin(GL_QUADS); 
  glTexCoord2f(cx, cz); glVertex3f(-r ,1.0f,-r);
  glTexCoord2f(cx,  cx); glVertex3f(-r,1.0f,r);
  glTexCoord2f(cz,  cx); glVertex3f( r,1.0f,r);
  glTexCoord2f(cz, cz); glVertex3f( r ,1.0f,-r);
 glEnd();
 
 // Common Axis Z - BACK side
 glBindTexture(GL_TEXTURE_2D,skyTexture[1].texID);
 glBegin(GL_QUADS);  
  glTexCoord2f(cx,cz);  glVertex3f(-r,-1.0f,-r);
  glTexCoord2f(cx,cx);  glVertex3f(-r,-1.0f, r);
  glTexCoord2f(cz,cx);  glVertex3f( r,-1.0f, r);
  glTexCoord2f(cz,cz);  glVertex3f( r,-1.0f,-r);
 glEnd();
 
 // Common Axis X - Left side
 glBindTexture(GL_TEXTURE_2D,skyTexture[2].texID);
 glBegin(GL_QUADS);  
  glTexCoord2f(cx,cx); glVertex3f(-1.0f, -r, r); 
  glTexCoord2f(cz,cx); glVertex3f(-1.0f,  r, r);
  glTexCoord2f(cz,cz); glVertex3f(-1.0f,  r,-r);
  glTexCoord2f(cx,cz); glVertex3f(-1.0f, -r,-r);  
 glEnd();
 
 // Common Axis X - Right side
 glBindTexture(GL_TEXTURE_2D,skyTexture[3].texID);
 glBegin(GL_QUADS);  
  glTexCoord2f( cx,cx); glVertex3f(1.0f, -r, r); 
  glTexCoord2f(cz, cx); glVertex3f(1.0f,  r, r);
  glTexCoord2f(cz, cz); glVertex3f(1.0f,  r,-r);
  glTexCoord2f(cx, cz); glVertex3f(1.0f, -r,-r);
 glEnd();
 
 // Common Axis Y - Draw Up side
 glBindTexture(GL_TEXTURE_2D,skyTexture[4].texID);
 glBegin(GL_QUADS);  
  glTexCoord2f(cz, cz); glVertex3f( r, -r,1.0f);
  glTexCoord2f(cx, cz); glVertex3f( r,  r,1.0f);
  glTexCoord2f(cx, cx); glVertex3f(-r,  r,1.0f);
  glTexCoord2f(cz, cx); glVertex3f(-r, -r,1.0f);
 glEnd();
 
 // Common Axis Y - Down side
 glBindTexture(GL_TEXTURE_2D,skyTexture[5].texID);
 glBegin(GL_QUADS);  
  glTexCoord2f(cz,cz);  glVertex3f( r, -r,-1.0f);
  glTexCoord2f( cx,cz); glVertex3f( r,  r,-1.0f);
  glTexCoord2f( cx,cx); glVertex3f(-r,  r,-1.0f);
  glTexCoord2f(cz, cx); glVertex3f(-r, -r,-1.0f);
 glEnd();
 
 glPopMatrix();
 return TRUE;
}
BOOL CMGTerrain::LoadSkyTexture(char *filename,int n)
{
  skyTexture[n].LoadTexture(filename);
 glGenTextures(1, &skyTexture[n].texID);
 glBindTexture(GL_TEXTURE_2D, skyTexture[n].texID);
   
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); //or GL_CLAMP
 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); //or GL_CLAMP
 switch (skyTexture[n].textureType)
 {
 case BMP:
  gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, skyTexture[n].width, skyTexture[n].height,
     GL_RGB, GL_UNSIGNED_BYTE, skyTexture[n].data);
  break;
 case PCX:
  gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA,skyTexture[n].width, skyTexture[n].height,
     GL_RGBA, GL_UNSIGNED_BYTE, skyTexture[n].data);
  break;
 case TGA:
  gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGB, skyTexture[n].width, skyTexture[n].height,
     GL_RGB, GL_UNSIGNED_BYTE, skyTexture[n].data);
  break;
 default:
  break;
 }
   return TRUE;
}
float  CMGTerrain::GetHeight(float x, float z)
{
   float projCameraX = x / MAP_SCALE;
   float projCameraZ = -z / MAP_SCALE;

 int hflCol0 = int(projCameraX);
 int hflRow0 = int(projCameraZ);
 int hflCol1 = hflCol0 + 1;
 int hflRow1 = hflRow0 + 1;
 float h00;
 float h01;
 float h11;
 float h10;
  h00=GetfloatBuf(g_terrain,hflCol0 + hflRow0*MAP_X,1,3);
  h01=GetfloatBuf(g_terrain,hflCol1 + hflRow0*MAP_X,1,3);
  h11=GetfloatBuf(g_terrain,hflCol1 + hflRow1*MAP_X,1,3);
  h10=GetfloatBuf(g_terrain,hflCol0 + hflRow1*MAP_X,1,3);

 float tx = projCameraX - float(hflCol0);
 float ty = projCameraZ - float(hflRow0);

 float txty = tx * ty;
 return h00 * (1.0f - ty - tx + txty)
     + h01 * (tx - txty)
     + h11 * txty
     + h10 * (ty - txty);
}
 
/*
 TEXTURE.H
 The CTexture class
 OpenGL Game Programming
 Author: Kevin Hawkins
 Date: 3/29/2001
 Description: The CTexture class represents a single texture
      object in the engine. To load a texture,
      you only need to call the LoadTexture() function.
*/
#ifndef __TEXTURE_H
#define __TEXTURE_H
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
 
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gl/gl.h>
#include <gl/glu.h>
#define BITMAP_ID 0x4D42  // the universal bitmap ID
enum texTypes_t
{
 PCX,
 BMP,
 TGA
};
// only partial pcx file header
typedef struct
{
 unsigned char manufacturer;
 unsigned char version;
 unsigned char encoding;
 unsigned char bits;
 unsigned char xMin;
 unsigned char yMin;
 unsigned char xMax;
 unsigned char yMax;
 unsigned char *palette;
} PCXHEADER;
typedef struct
{
 unsigned char imageTypeCode;
 short int imageWidth;
 short int imageHeight;
 unsigned char bitCount;
} TGAHEADER;
class CTexture
{
private:
 long int scaledWidth;
 long int scaledHeight;
 unsigned char *palette;
 unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader);
 unsigned char *LoadBitmapFileWithAlpha(char *filename, BITMAPINFOHEADER *bitmapInfoHeader);
 unsigned char *LoadPCXFile(char *filename, PCXHEADER *pcxHeader);
 unsigned char *LoadTGAFile(char *filename, TGAHEADER *tgaHeader);
 void LoadPCXTexture(char *filename);
 void LoadBMPTexture(char *filename);
 void LoadTGATexture(char *filename);
public:
 texTypes_t textureType;
 unsigned char tgaImageCode; // 0 = not TGA image, 2 = color, 3 = greyscale
 int width;
 int height;
 int bitDepth;
 unsigned int texID;
 unsigned char *data;
 CTexture() { data = NULL; palette = NULL; }
 ~CTexture() { Unload(); }
 void LoadTexture(char *filename);
 void Unload()
 {
  glDeleteTextures(1, &texID);
  if (data != NULL)
   free(data);
  if (palette != NULL)
   free(palette);
  
  data = NULL;
  palette = NULL;
 }
};
#endif
 
/*
texture.cpp
 The CTexture class
 OpenGL Game Programming
 Author: Kevin Hawkins
 Date: 3/29/2001
 Description: The CTexture class represents a single texture
      object in the engine. To load a texture,
      you only need to call the LoadTexture() function.
*/
#include "texture.h"
// LoadBitmapFile
// desc: Returns a pointer to the bitmap image of the bitmap specified
//       by filename. Also returns the bitmap header information.
//   No support for 8-bit bitmaps.
unsigned char *CTexture::LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{
 FILE *filePtr;       // the file pointer
 BITMAPFILEHEADER bitmapFileHeader;  // bitmap file header
 unsigned char  *bitmapImage;   // bitmap image data
 int    imageIdx = 0;   // image index counter
 unsigned char  tempRGB;    // swap variable
 // open filename in "read binary" mode
 filePtr = fopen(filename, "rb");
 if (filePtr == NULL)
  return NULL;
 // read the bitmap file header
 fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);
 
 // verify that this is a bitmap by checking for the universal bitmap id
 if (bitmapFileHeader.bfType != BITMAP_ID)
 {
  fclose(filePtr);
  return NULL;
 }
 // read the bitmap information header
 fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);
 // move file pointer to beginning of bitmap data
 fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
 // allocate enough memory for the bitmap image data
 bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);
 // verify memory allocation
 if (!bitmapImage)
 {
  free(bitmapImage);
  fclose(filePtr);
  return NULL;
 }
 // read in the bitmap image data
 fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);
 // make sure bitmap image data was read
 if (bitmapImage == NULL)
 {
  fclose(filePtr);
  return NULL;
 }
 // swap the R and B values to get RGB since the bitmap color format is in BGR
 for (imageIdx = 0; imageIdx < (int)bitmapInfoHeader->biSizeImage; imageIdx+=3)
 {
  tempRGB = bitmapImage[imageIdx];
  bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
  bitmapImage[imageIdx + 2] = tempRGB;
 }
 // close the file and return the bitmap image data
 fclose(filePtr);
 return bitmapImage;
}
/*****************************************************************************
 LoadBitmapFileWithAlpha
 Loads a bitmap file normally, and then adds an alpha component to use for
 blending
*****************************************************************************/
unsigned char *CTexture::LoadBitmapFileWithAlpha(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{
  unsigned char *bitmapImage = LoadBitmapFile(filename, bitmapInfoHeader);
  unsigned char *bitmapWithAlpha = (unsigned char *)malloc(bitmapInfoHeader->biSizeImage * 4 / 3);
  // loop through the bitmap data
  for (int src = 0, dst = 0; src < bitmapInfoHeader->biSizeImage; src +=3, dst +=4)
  {
    // if the pixel is black, set the alpha to 0. Otherwise, set it to 255.
    if (bitmapImage[src] == 0 && bitmapImage[src+1] == 0 && bitmapImage[src+2] == 0)
      bitmapWithAlpha[dst+3] = 0;
    else
      bitmapWithAlpha[dst+3] = 0xFF;
    // copy pixel data over
    bitmapWithAlpha[dst] = bitmapImage[src];
    bitmapWithAlpha[dst+1] = bitmapImage[src+1];
    bitmapWithAlpha[dst+2] = bitmapImage[src+2];
  }
  free(bitmapImage);
  return bitmapWithAlpha;
} // end LoadBitmapFileWithAlpha()
// LoadPCXFile()
// desc: loads a PCX file into memory
unsigned char *CTexture::LoadPCXFile(char *filename, PCXHEADER *pcxHeader)
{
     int idx = 0;                  // counter index
     int c;                             // used to retrieve a char from the file
     int i;                             // counter index
     int numRepeat;     
     FILE *filePtr;                // file handle
     int width;                         // pcx width
     int height;                        // pcx height
     unsigned char *pixelData;     // pcx image data
     unsigned char *paletteData;   // pcx palette data
     // open PCX file
     filePtr = fopen(filename, "rb");
     if (filePtr == NULL)
          return NULL;
     // retrieve first character; should be equal to 10
     c = getc(filePtr);
     if (c != 10)
     {
          fclose(filePtr);
          return NULL;
     }
     // retrieve next character; should be equal to 5
     c = getc(filePtr);
     if (c != 5)
     {
          fclose(filePtr);
          return NULL;
     }
     // reposition file pointer to beginning of file
     rewind(filePtr);
     // read 4 characters of data to skip
     fgetc(filePtr);
     fgetc(filePtr);
     fgetc(filePtr);
     fgetc(filePtr);
     // retrieve leftmost x value of PCX
     pcxHeader->xMin = fgetc(filePtr);       // loword
     pcxHeader->xMin |= fgetc(filePtr) << 8; // hiword
     // retrieve bottom-most y value of PCX
     pcxHeader->yMin = fgetc(filePtr);       // loword
     pcxHeader->yMin |= fgetc(filePtr) << 8; // hiword
     // retrieve rightmost x value of PCX
     pcxHeader->xMax = fgetc(filePtr);       // loword
     pcxHeader->xMax |= fgetc(filePtr) << 8; // hiword
     // retrieve topmost y value of PCX
     pcxHeader->yMax = fgetc(filePtr);       // loword
     pcxHeader->yMax |= fgetc(filePtr) << 8; // hiword
     // calculate the width and height of the PCX
     width = pcxHeader->xMax - pcxHeader->xMin + 1;
     height = pcxHeader->yMax - pcxHeader->yMin + 1;
     // allocate memory for PCX image data
     pixelData = (unsigned char*)malloc(width*height);
     // set file pointer to 128th byte of file, where the PCX image data starts
     fseek(filePtr, 128, SEEK_SET);
    
     // decode the pixel data and store
     while (idx < (width*height))
     {
          c = getc(filePtr);
          if (c > 0xbf)
          {
               numRepeat = 0x3f & c;
               c = getc(filePtr);
               for (i = 0; i < numRepeat; i++)
               {
                    pixelData[idx++] = c;
               }
          }
          else
               pixelData[idx++] = c;
          fflush(stdout);
     }
     // allocate memory for the PCX image palette
     paletteData = (unsigned char*)malloc(768);
     // palette is the last 769 bytes of the PCX file
     fseek(filePtr, -769, SEEK_END);
     // verify palette; first character should be 12
     c = getc(filePtr);
     if (c != 12)
     {
          fclose(filePtr);
          return NULL;
     }
     // read and store all of palette
     for (i = 0; i < 768; i++)
     {
          c = getc(filePtr);
          paletteData[i] = c;
     }
     // close file and store palette in header
     fclose(filePtr);
     pcxHeader->palette = paletteData;
     // return the pixel image data
     return pixelData;
}
// LoadPCXTexture()
// desc: loads a PCX image file as a texture
void CTexture::LoadPCXTexture(char *filename)
{
     PCXHEADER texInfo;            // header of texture
//     texture_t *thisTexture;       // the texture
     unsigned char *unscaledData;// used to calculate pcx
     int i;                             // index counter
     int j;                             // index counter
     int w;                         // width of texture
     int h;                        // height of texture
     // load the PCX file into the texture struct
     data = LoadPCXFile(filename, &texInfo);
     if (data == NULL)
     {
          free(data);
     //     return NULL;
     }
     // store the texture information
     palette = texInfo.palette;
     width = texInfo.xMax - texInfo.xMin + 1;
     height = texInfo.yMax - texInfo.yMin + 1;
     textureType = PCX;
 w = width;
     h = height;
     // allocate memory for the unscaled data
     unscaledData = (unsigned char*)malloc(w*h*4);
     // store the unscaled data via the palette
     for (j = 0; j < h; j++)
     {
          for (i = 0; i < w; i++)
          {
               unscaledData[4*(j*w+i)+0] = (unsigned char)palette[3*data[j*w+i]+0];
               unscaledData[4*(j*w+i)+1] = (unsigned char)palette[3*data[j*w+i]+1];
               unscaledData[4*(j*w+i)+2] = (unsigned char)palette[3*data[j*w+i]+2];
               unscaledData[4*(j*w+i)+3] = (unsigned char)255;
          }
     }
     // find width and height's nearest greater power of 2
     // find width's
     i = 0;
     while (w)
     {
          w /= 2;
          i++;
     }
     scaledHeight = (long)pow(2, i-1);
     // find height's
     i = 0;
     while (h)
     {
          h /= 2;
          i++;
     }
     scaledWidth = (long)pow(2, i-1);
     // clear the texture data
     if (data != NULL)
     {
          free(data);
          data = NULL;
     }
     // reallocate memory for the texture data
     data = (unsigned char*)malloc(scaledWidth*scaledHeight*4);
    
     // use the GL utility library to scale the texture to the unscaled dimensions
     gluScaleImage(GL_RGBA, this->width, this->height, GL_UNSIGNED_BYTE, unscaledData, scaledWidth, scaledHeight, GL_UNSIGNED_BYTE, data);
 free(unscaledData);
//     return thisTexture;
}
// LoadBMPTexture()
// desc: loads a texture of the BMP format
void CTexture::LoadBMPTexture(char *filename)
{
 BITMAPINFOHEADER texInfo;  // BMP header
 // store BMP data in texture
 data = LoadBitmapFileWithAlpha(filename, &texInfo);
 if (data == NULL)
 {
  free(data);
 }
 
 // store texture information
 width = texInfo.biWidth;
 height = texInfo.biHeight;
 palette = NULL;
 scaledHeight = 0;
 scaledWidth = 0;
 textureType = BMP;
}
// LoadTexture()
// desc: loads a texture given the filename
void CTexture::LoadTexture(char *filename)
{
 char *extStr;
 // get extension from filename
 extStr = strchr(filename, '.');
 extStr++;
 // set the texture type based on extension of filename
 if ((strcmpi(extStr, "BMP") == 0) || (strcmpi(extStr, "bmp") == 0))
  LoadBMPTexture(filename);
 else if ((strcmpi(extStr, "PCX") == 0) || (strcmpi(extStr, "pcx") == 0) )
  LoadPCXTexture(filename);
 
 else if ((strcmpi(extStr, "TGA") == 0) || (strcmpi(extStr, "tga") == 0) )
  LoadTGATexture(filename);
}
// LoadTGAFile()
// desc: loads a TGA file defined by filename
unsigned char *CTexture::LoadTGAFile(char *filename, TGAHEADER *tgaHeader)
{
 FILE *filePtr;
 unsigned char ucharBad; // garbage data
 short int sintBad;  // garbage data
 long imageSize;  // size of TGA image
 int colorMode;   // 4 for RGBA, 3 for RGB
 long imageIdx;   // counter variable
 unsigned char colorSwap; // swap variable
 unsigned char *imageData; // the TGA data
 // open the TGA file
 filePtr = fopen(filename, "rb");
 if (!filePtr)
  return NULL;
 
 // read first two bytes of garbage
 fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
 fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
 // read in the image type
 fread(&tgaHeader->imageTypeCode, sizeof(unsigned char), 1, filePtr);
 // for our purposes, the image type should be either a 2 or a 3
 if ((tgaHeader->imageTypeCode != 2) && (tgaHeader->imageTypeCode != 3))
 {
  fclose(filePtr);
  return NULL;
 }
 // read 13 bytes of garbage data
 fread(&sintBad, sizeof(short int), 1, filePtr);
 fread(&sintBad, sizeof(short int), 1, filePtr);
 fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
 fread(&sintBad, sizeof(short int), 1, filePtr);
 fread(&sintBad, sizeof(short int), 1, filePtr);
 // read image dimensions
 fread(&tgaHeader->imageWidth, sizeof(short int), 1, filePtr);
 fread(&tgaHeader->imageHeight, sizeof(short int), 1, filePtr);
 // read bit depth
 fread(&tgaHeader->bitCount, sizeof(unsigned char), 1, filePtr);
 // read garbage
 fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
 // colormode -> 3 = BGR, 4 = BGRA
 colorMode = tgaHeader->bitCount / 8;
 imageSize = tgaHeader->imageWidth * tgaHeader->imageHeight * colorMode;
 // allocate memory for image data
 imageData = (unsigned char*)malloc(sizeof(unsigned char)*imageSize);
 // read image data
 fread(imageData, sizeof(unsigned char), imageSize, filePtr);
 // change BGR to RGB so OpenGL can use the data
 for (imageIdx = 0; imageIdx < imageSize; imageIdx += colorMode)
 {
  colorSwap = imageData[imageIdx];
  imageData[imageIdx] = imageData[imageIdx+2];
  imageData[imageIdx + 2] = colorSwap;
 }
 // close the file
 fclose(filePtr);
 return imageData;
}
// LoadTGATexture()
// desc: loads a TGA as a texture
void CTexture::LoadTGATexture(char *filename)
{
 TGAHEADER tga;  // BMP header
 // store BMP data in texture
 data = LoadTGAFile(filename, &tga);
 if (data == NULL)
 {
  free(data);
 }
 
 // store texture information
 width = tga.imageWidth;
 height = tga.imageHeight;
 palette = NULL;
 scaledHeight = 0;
 scaledWidth = 0;
 tgaImageCode = tga.imageTypeCode;
 bitDepth = tga.bitCount;
 textureType = TGA;
}
定义高程地形类
CMGTerrain MyMap(32,1,FALSE);
初始化时使用以下代码。
 MyMap.SetUV(0.5,0.5);//设置纹理的插值密度
 MyMap.LoadTextures("texture.tga");//加载地形图纹理
 MyMap.Create("bigmap.bmp");//加载地形
//天空盒六个面的纹理
 MyMap.LoadSkyTexture("stars.tga",0);
 MyMap.LoadSkyTexture("stars.tga",1);
 MyMap.LoadSkyTexture("stars.tga",2);
 MyMap.LoadSkyTexture("stars.tga",3);
 MyMap.LoadSkyTexture("stars.tga",4);
 MyMap.LoadSkyTexture("stars.tga",5);
 
绘制时直接调用
MyMap.Draw();
 
效果如下图
 

高程地形效果

网站问题代码发不全,报错行将下列语句的“&”去掉: 

  m_bi&w&i&d&t&h&=&bit&map&InfoHeader->bi&Width;


 

技术 | 阅读 5041 次
文章评论,共0条
游客请输入验证码
浏览61117次
文章分类