www.pudn.com > VC中OpenGL编程实现虚拟现实.rar > House.cpp, change:2003-04-07,size:10590b
// House.cpp: implementation of the CHouse class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "House.h"
#include <time.h>
#include <math.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CHouse::CHouse()
{
// 初始化观察位置信息
m_ViewPos.Angle=30.0;
m_ViewPos.Near=20.0;
m_ViewPos.ex=100.0;
m_ViewPos.ey=1.0;
m_ViewPos.ez=45.0;
m_ViewPos.cx=-5.0;
m_ViewPos.cy=1.0;
m_ViewPos.cz=5.0;
}
CHouse::~CHouse()
{
}
// 读取House.dat,得到房屋三维数据
BOOL CHouse::GetHouseData()
{
int i,j,l;
FILE *fp;
char stemp[100];
POINT3D *plist;
INT4U nAllVertexNum;
INT4U *pchlist;
// 打开文件
strcpy(m_cHouseDataFile,"House.dat");
fp = fopen( m_cHouseDataFile, "r" );
if ( fp == NULL )
{
return FALSE;
}
fseek( fp, 0, SEEK_SET);
// 得到纹理列表
fscanf( fp, "%s", stemp);
while( strcmp( stemp,"TextureNum" ) != 0) fscanf( fp, "%s", stemp);
fscanf( fp, "%d", &m_nTextureNum );
m_TextureList = (TEXTURE2D **)malloc( sizeof(TEXTURE2D)*(m_nTextureNum+1));
for(i=1; i=m_nTextureNum; i++)
{
m_TextureList[i] = (TEXTURE2D *)malloc( sizeof(TEXTURE2D));
fscanf( fp, "%s%s", m_TextureList[i]->fname, stemp );
if ( strcmp( stemp,"GL_REPEAT" ) == 0)
m_TextureList[i]->type = GL_REPEAT;
else if ( strcmp( stemp,"GL_CLAMP" ) == 0)
m_TextureList[i]->type = GL_CLAMP;
}
// 得到房屋中物体个数
fscanf( fp, "%s", stemp);
while( strcmp( stemp,"ObjectNum" ) != 0) fscanf(fp,"%s",stemp);
fscanf( fp, "%ld", &m_nObjectNum);
m_ObjectList = (OBJECT *)malloc( sizeof(OBJECT ) * m_nObjectNum);
for(i = 0; i m_nObjectNum; i ++ )
{
fscanf( fp, "%s", stemp);
while( strcmp( stemp,"SurfaceNum" ) != 0) fscanf(fp,"%s",stemp);
fscanf( fp, "%ld", &(m_ObjectList[i].SurfNum) );
m_ObjectList[i].surflist = (SURFACE *)malloc( sizeof(SURFACE) * m_ObjectList[i].SurfNum);
for(j = 0; j m_ObjectList[i].SurfNum; j ++ )
{
// 得到每个物体的面的点、纹理、三角形和方形的信息
fscanf( fp, "%s", stemp);
while( strcmp( stemp,"TextureId" ) != 0) fscanf(fp,"%s",stemp);
fscanf( fp, "%d", &(m_ObjectList[i].surflist[j].texId) );
fscanf( fp, "%s", stemp);
while( strcmp( stemp,"pointnum" ) != 0) fscanf(fp,"%s",stemp);
fscanf( fp, "%d", &(m_ObjectList[i].surflist[j].pointn) );
fscanf( fp, "%s", stemp);
while( strcmp( stemp,"triangle" ) != 0) fscanf(fp,"%s",stemp);
fscanf( fp, "%d", &(m_ObjectList[i].surflist[j].triangle) );
fscanf( fp, "%s", stemp);
while( strcmp( stemp,"quadrangle" ) != 0) fscanf(fp,"%s",stemp);
fscanf( fp, "%d", &(m_ObjectList[i].surflist[j].quadric) );
// 得到点列表
m_ObjectList[i].surflist[j].pointlist = (POINT3D*)malloc(sizeof(POINT3D) *
m_ObjectList[i].surflist[j].pointn);
plist = m_ObjectList[i].surflist[j].pointlist;
for( l = 0; l m_ObjectList[i].surflist[j].pointn ; l ++ )
fscanf( fp, "%f%f%f%f%f%f%f%f",
&(plist[l].r), &(plist[l].g), &(plist[l].b),
&(plist[l].u), &(plist[l].v),
&(plist[l].x), &(plist[l].y), &(plist[l].z) );
// 得到面连接信息
nAllVertexNum = m_ObjectList[i].surflist[j].triangle * 3 +
m_ObjectList[i].surflist[j].quadric *4 ;
m_ObjectList[i].surflist[j].patchlist = (INT4U *)malloc( sizeof(INT4U) * nAllVertexNum);
pchlist = m_ObjectList[i].surflist[j].patchlist;
for( l = 0; l nAllVertexNum; l ++ )
fscanf( fp, "%ld", &(pchlist[l]) );
}
}
fclose(fp);
return TRUE;
}
// 设置绘制房屋所需参数
void CHouse::InitDraw()
{
glShadeModel ( GL_SMOOTH );
glDepthFunc ( GL_LESS );
glEnable ( GL_DEPTH_TEST );
glMatrixMode ( GL_PROJECTION );
glLoadIdentity();
glMatrixMode ( GL_MODELVIEW );
glLoadIdentity();
gluPerspective ( m_ViewPos.Angle, (float)1000/(float)800, m_ViewPos.Near, 1000000000.0);
gluLookAt( m_ViewPos.ex, m_ViewPos.ey, m_ViewPos.ez, m_ViewPos.cx, m_ViewPos.cy, m_ViewPos.cz, 0.0, 1.0, 0.0);
}
// 绘制房屋
void CHouse::Draw(void)
{
int i, j, k, l, m, TexIndex;
POINT3D *plist;
INT4U *pchlist;
// 逐个创建房屋中的物体并贴上纹理
for(i = 0; i m_nObjectNum; i ++ )
for(j = 0; j m_ObjectList[i].SurfNum; j ++ )
{
// 逐个创建物体中的每个面并贴上纹理
TexIndex = m_ObjectList[i].surflist[j].texId;
if( TexIndex > 0 )
InitHouseTexture( TexIndex ); // 创建纹理
plist = m_ObjectList[i].surflist[j].pointlist;
pchlist = m_ObjectList[i].surflist[j].patchlist;
// 贴三角形
l = 0;
for ( k = 0; k m_ObjectList[i].surflist[j].triangle; k ++)
{
glBegin( GL_TRIANGLES ); // 开始绘制三角形
for( m = 0; m 3; m ++ )
{
glColor3f ( plist[pchlist[l]].r,plist[pchlist[l]].g,plist[pchlist[l]].b ); // 设置绘制颜色
glTexCoord2f( plist[pchlist[l]].u, plist[pchlist[l]].v ); // 设置纹理坐标
glVertex3f( plist[pchlist[l]].x, plist[pchlist[l]].y, plist[pchlist[l]].z ); // 指定顶点
l ++;
}
glEnd(); // 结束绘制三角形
}
// 贴方形
for ( k = 0; k m_ObjectList[i].surflist[j].quadric; k ++)
{
glBegin( GL_QUADS ); // 开始绘制多边形
for( m = 0; m 4; m ++ )
{
glColor3f ( plist[pchlist[l]].r, plist[pchlist[l]].g, plist[pchlist[l]].b ); // 设置绘制颜色
glTexCoord2f( plist[pchlist[l]].u, plist[pchlist[l]].v ); // 设置纹理坐标
glVertex3f( plist[pchlist[l]].x, plist[pchlist[l]].y, plist[pchlist[l]].z ); // 指定顶点
l ++;
}
glEnd(); // 结束绘制多边形
}
glFlush(); // 强制OpenGL操作完成
glDisable(GL_TEXTURE_2D); //关闭纹理
}
}
// 释放房屋三维数据
void CHouse::FreeHouseData()
{
int i, j;
for( i=0; i<m_nObjectNum; i++)
{
for( j=0; j<m_ObjectList[i].SurfNum; j++)
{
free(m_ObjectList[i].surflist[j].pointlist);
free(m_ObjectList[i].surflist[j].patchlist);
}
free( m_ObjectList[i].surflist );
}
free(m_ObjectList);
for(i=1; i=m_nTextureNum; i++)
free(m_TextureList[i]);
free(m_TextureList);
}
// 加载房屋纹理位图文件
unsigned char* CHouse::LoadHouseBMP( INT2U TexIndex, INT2U *rslx, INT2U *rsly )
{
unsigned char *image;
FILE *fp;
INT2U srcx, srcy;
INT4U i, j;
char m_cBMPFileName[30];
unsigned char *SImageData;
int rc;
int width, height;
strcpy( m_cBMPFileName, m_TextureList[TexIndex]->fname);
// 打开纹理位图文件
fp = fopen(m_cBMPFileName,"rb");
if(!fp) return 0;
fseek(fp,18L,0);
rc=fread(&width,sizeof(long),1,fp);
rc=fread(&height,sizeof(long),1,fp);
*rslx=srcx=width; *rsly=srcy=height;
fseek(fp,54L,0);
image = (unsigned char *)malloc(width*height*3);
rc=fread(image,width*height*3,1,fp); // 读取纹理位图数据
fclose(fp);
SImageData = (unsigned char *)malloc(srcx*srcy*3);
for(i=0; i<srcx; i++) {
for(j=0; j<srcy; j++) {
(unsigned char)*(SImageData+i*srcx*3+j*3+0) = (unsigned char)*(image+i*srcx*3+j*3+2);
(unsigned char)*(SImageData+i*srcx*3+j*3+1) = (unsigned char)*(image+i*srcx*3+j*3+1);
(unsigned char)*(SImageData+i*srcx*3+j*3+2) = (unsigned char)*(image+i*srcx*3+j*3+0);
}
}
free(image);
return( SImageData );
}
// 创建房屋纹理
void CHouse::InitHouseTexture( int TexIndex )
{
INT2U TextureType;
unsigned char *TextureData;
static int OldIndex = -1;
if(TexIndex=0) return;
if(TexIndex == OldIndex)
{
glEnable(GL_TEXTURE_2D); // 开启纹理贴图
return;
}
TextureData = m_BMPData[TexIndex-1]; // 加载纹理位图数据
TextureType = m_TextureList[TexIndex]->type; // 加载纹理贴图方式
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// 设置纹理参数
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, TextureType);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, TextureType);
// 创建纹理
glTexImage2D( GL_TEXTURE_2D, 0, 3, m_nTextureWidth[TexIndex-1], m_nTextureHeight[TexIndex-1],
0,GL_RGB, GL_UNSIGNED_BYTE, TextureData );
glEnable(GL_TEXTURE_2D);
OldIndex = TexIndex;
}
// 加载房屋纹理位图数据
void CHouse::LoadHouseTexture()
{
int i;
for (i=0; i <m_nTextureNum ; i++)
m_BMPData[i] = LoadHouseBMP( i+1, &m_nTextureWidth[i], &m_nTextureHeight[i] );
}
// 释放房屋纹理
void CHouse::FreeHouseTexture()
{
int i;
for (i=0; i <m_nTextureNum ; i++)
free(m_BMPData[i]);
}
// 当观察点改变时重新绘制场景的函数
void CHouse::ChangeViewPos(int type, GLfloat amount)
{
GLfloat a;
switch(type)
{
case FORWARD: // 观察者前进,场景中景物变大
a = sqrt((m_ViewPos.cx-m_ViewPos.ex)*(m_ViewPos.cx-m_ViewPos.ex)+(m_ViewPos.cz-m_ViewPos.ez)*(m_ViewPos.cz-m_ViewPos.ez));
m_ViewPos.ex = (amount*(m_ViewPos.cx-m_ViewPos.ex)+a*m_ViewPos.ex) / a;
m_ViewPos.ez = (amount*(m_ViewPos.cz-m_ViewPos.ez)+a*m_ViewPos.ez) / a;
m_ViewPos.cx = (amount*(m_ViewPos.cx-m_ViewPos.ex)+a*m_ViewPos.cx) / a;
m_ViewPos.cz = (amount*(m_ViewPos.cz-m_ViewPos.ez)+a*m_ViewPos.cz) / a;
break;
case LOOKHORIZONTAL: // 观察者左右(水平方向)观察场景
m_ViewPos.cx = (m_ViewPos.cx-m_ViewPos.ex)*(float)cos(amount/360.0f) + (m_ViewPos.cz-m_ViewPos.ez)*(float)sin(amount/360.0f)+m_ViewPos.ex;
m_ViewPos.cz = (m_ViewPos.cz-m_ViewPos.ez)*(float)cos(amount/360.0f) - (m_ViewPos.cx-m_ViewPos.ex)*(float)sin(amount/360.0f)+m_ViewPos.ez;
break;
case LOOKVERTICAL: // 观察者上下(垂直方向)观察场景
m_ViewPos.cy += amount;
break;
case UP: // 观察者位置上下(垂直方向)改变,被观察点位置不变
m_ViewPos.ey += amount;
break;
}
// 重新绘制场景
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(m_ViewPos.ex, m_ViewPos.ey, m_ViewPos.ez, m_ViewPos.cx, m_ViewPos.cy, m_ViewPos.cz, 0.0f,1.0f,0.0f);
}