作者在 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__
//作者:刘鑫
//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
#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();
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];//天空纹理
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);
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;
GLuint *g_indexArray;
float *g_terrain;
float *g_colorArray;
float *g_texcoordArray;
PFNGLLOCKARRAYSEXTPROC glLockArraysEXT;
PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT;
};
PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT;
};
#endif
//-----------------------------------------------
//CMGTerrain.cpp
//作者:刘鑫
//E-MAIL:LIUXIN1984121@TOM.COM
//时间:2009,7,25
//说明CMGTerrain类用于生成地形
//-----------------------------------------------
//作者:刘鑫
//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;
{
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;
}
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_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;
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;
}
{
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;
}
{
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);
{
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");
}
{
glLockArraysEXT = (PFNGLLOCKARRAYSEXTPROC) wglGetProcAddress("glLockArraysEXT");
glUnlockArraysEXT = (PFNGLUNLOCKARRAYSEXTPROC) wglGetProcAddress("glUnlockArraysEXT");
}
if (glLockArraysEXT)
glLockArraysEXT(0, MAP_X * MAP_Z * 6);
return TRUE;
}
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;
}
{
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;
}
{
float rebuf;
rebuf=(*(buf+maxw*row+col));
return rebuf;
}
void CMGTerrain::InitializeArrays()
{
int index = 0;
int currentVertex;
float wbuf;
float u_w;
{
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;
{
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;
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);
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);
}
}
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++;
}
}
{
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);
}
}
}
{
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;
{
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;
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;
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];
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);
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
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;
}
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);
{
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);
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();
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;
}
return TRUE;
}
BOOL CMGTerrain::DrawSky()
{
int WORLD_SIZE;
{
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();
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);
{
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
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;
}
{
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;
{
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;
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);
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);
}
+ h01 * (tx - txty)
+ h11 * txty
+ h10 * (ty - txty);
}
/*
TEXTURE.H
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.
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 __TEXTURE_H
#define WIN32_LEAN_AND_MEAN
#define WIN32_EXTRA_LEAN
#define WIN32_EXTRA_LEAN
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <gl/gl.h>
#include <gl/glu.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
};
{
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 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;
{
unsigned char imageTypeCode;
short int imageWidth;
short int imageHeight;
unsigned char bitCount;
} TGAHEADER;
class CTexture
{
private:
long int scaledWidth;
long int scaledHeight;
{
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);
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
texTypes_t textureType;
unsigned char tgaImageCode; // 0 = not TGA image, 2 = color, 3 = greyscale
int width;
int height;
int bitDepth;
unsigned int texID;
int height;
int bitDepth;
unsigned int texID;
unsigned char *data;
CTexture() { data = NULL; palette = NULL; }
~CTexture() { Unload(); }
~CTexture() { Unload(); }
void LoadTexture(char *filename);
void Unload()
{
glDeleteTextures(1, &texID);
void Unload()
{
glDeleteTextures(1, &texID);
if (data != NULL)
free(data);
if (palette != NULL)
free(palette);
data = NULL;
palette = 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.
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
// 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;
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;
}
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);
fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);
// move file pointer to beginning of bitmap data
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
// allocate enough memory for the bitmap image data
bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);
bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);
// verify memory allocation
if (!bitmapImage)
{
free(bitmapImage);
fclose(filePtr);
return NULL;
}
if (!bitmapImage)
{
free(bitmapImage);
fclose(filePtr);
return NULL;
}
// read in the bitmap image data
fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);
fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);
// make sure bitmap image data was read
if (bitmapImage == NULL)
{
fclose(filePtr);
return NULL;
}
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;
}
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;
}
fclose(filePtr);
return bitmapImage;
}
/*****************************************************************************
LoadBitmapFileWithAlpha
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);
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;
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];
}
bitmapWithAlpha[dst] = bitmapImage[src];
bitmapWithAlpha[dst+1] = bitmapImage[src+1];
bitmapWithAlpha[dst+2] = bitmapImage[src+2];
}
free(bitmapImage);
return bitmapWithAlpha;
} // end LoadBitmapFileWithAlpha()
} // 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
// 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;
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;
}
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;
}
c = getc(filePtr);
if (c != 5)
{
fclose(filePtr);
return NULL;
}
// reposition file pointer to beginning of file
rewind(filePtr);
rewind(filePtr);
// read 4 characters of data to skip
fgetc(filePtr);
fgetc(filePtr);
fgetc(filePtr);
fgetc(filePtr);
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
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
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
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
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;
width = pcxHeader->xMax - pcxHeader->xMin + 1;
height = pcxHeader->yMax - pcxHeader->yMin + 1;
// allocate memory for PCX image data
pixelData = (unsigned char*)malloc(width*height);
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);
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;
{
pixelData[idx++] = c;
}
}
else
pixelData[idx++] = c;
fflush(stdout);
}
}
// allocate memory for the PCX image palette
paletteData = (unsigned char*)malloc(768);
paletteData = (unsigned char*)malloc(768);
// palette is the last 769 bytes of the PCX file
fseek(filePtr, -769, SEEK_END);
fseek(filePtr, -769, SEEK_END);
// verify palette; first character should be 12
c = getc(filePtr);
if (c != 12)
{
fclose(filePtr);
return NULL;
}
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;
}
for (i = 0; i < 768; i++)
{
c = getc(filePtr);
paletteData[i] = c;
}
// close file and store palette in header
fclose(filePtr);
pcxHeader->palette = paletteData;
fclose(filePtr);
pcxHeader->palette = paletteData;
// return the pixel image data
return pixelData;
}
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
// 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;
}
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;
palette = texInfo.palette;
width = texInfo.xMax - texInfo.xMin + 1;
height = texInfo.yMax - texInfo.yMin + 1;
textureType = PCX;
w = width;
h = height;
h = height;
// allocate memory for the unscaled data
unscaledData = (unsigned char*)malloc(w*h*4);
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;
}
}
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);
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);
i = 0;
while (h)
{
h /= 2;
i++;
}
scaledWidth = (long)pow(2, i-1);
// clear the texture data
if (data != NULL)
{
free(data);
data = NULL;
}
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);
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;
// return thisTexture;
}
// LoadBMPTexture()
// desc: loads a texture of the BMP format
void CTexture::LoadBMPTexture(char *filename)
{
BITMAPINFOHEADER texInfo; // BMP header
// 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;
}
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;
// desc: loads a texture given the filename
void CTexture::LoadTexture(char *filename)
{
char *extStr;
// get extension from filename
extStr = strchr(filename, '.');
extStr++;
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);
}
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
// 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);
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);
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;
}
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);
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);
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);
fread(&tgaHeader->bitCount, sizeof(unsigned char), 1, filePtr);
// read garbage
fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
fread(&ucharBad, sizeof(unsigned char), 1, filePtr);
// colormode -> 3 = BGR, 4 = BGRA
colorMode = tgaHeader->bitCount / 8;
imageSize = tgaHeader->imageWidth * tgaHeader->imageHeight * colorMode;
colorMode = tgaHeader->bitCount / 8;
imageSize = tgaHeader->imageWidth * tgaHeader->imageHeight * colorMode;
// allocate memory for image data
imageData = (unsigned char*)malloc(sizeof(unsigned char)*imageSize);
imageData = (unsigned char*)malloc(sizeof(unsigned char)*imageSize);
// read image data
fread(imageData, sizeof(unsigned char), imageSize, filePtr);
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;
}
for (imageIdx = 0; imageIdx < imageSize; imageIdx += colorMode)
{
colorSwap = imageData[imageIdx];
imageData[imageIdx] = imageData[imageIdx+2];
imageData[imageIdx + 2] = colorSwap;
}
// close the file
fclose(filePtr);
fclose(filePtr);
return imageData;
}
}
// LoadTGATexture()
// desc: loads a TGA as a texture
void CTexture::LoadTGATexture(char *filename)
{
TGAHEADER tga; // BMP header
// 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;
}
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.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.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();
效果如下图