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); 
}