场景漫游

实验三:场景漫游

win8.1+VS2013+GLUT


#include <math.h>
#include <glut.h>
#include <stdio.h> 
#include<iostream>  
#include <Windows.h>  

// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include<vector>

using namespace std;

#define BMP_Header_Length 54

/////设计目标/////////
//纹理贴图(内侧)√
//设置光源
//层次建模建立三维模型(桌椅)√
//扫面建模(花瓶)
//几何变换(放在桌子上)
//交互控制及观察√
//简单光照明(添加屋顶灯光)
//阴影计算
//光线跟踪算法,全局光照明
//场景漫游√
//地球仪(底座、支撑杆、地球)
//读取dragon.odj
/////////////////////

GLfloat EyeX = 5.0;
GLfloat EyeY = 0.0;
GLfloat EyeZ = 0.0;
GLfloat RdegreeX = 0.0;
GLfloat RdegreeZ = 0.0;
float PI = 3.14159f;
static int du=90,oldmy=-1,oldmx=-1; //du是视点绕y轴的角度,opengl里

默认y轴是上方向  
 
//场景漫游变量
// 追踪观察点的方向
static GLfloat s_eye[] = { 17.0,-3.0,0.0 };
static GLfloat s_at[] = { 0.0, -3.0,0.0 };
static GLfloat s_angle = -180.0;					

	//如果初始角度设置为0则初始面向X轴正方向,设置
//为-90面向Z轴负方向,符合默认情况下的设计习惯。
float rad;
float speed = 0.5;		//漫游速度

//灯光位置
GLfloat position_light[] = {10,2,22};	//x,y,z

//贴图变量
GLint room_ground;	//地面
GLint room_wall;	//墙
GLint room_up;	//房顶
GLint desk;		//桌子
GLint chair;	//椅子
GLint map;	//地图
GLint vase;	//花瓶
GLint dizuo;	//地球仪底座
GLint w,h,total_bytes; 
GLbyte *pixels = 0; 
GLint last_texture_ID;
GLuint texture_ID = 0;

//带贴图的正方体
void MyCube(float size ,GLint tex){
	glTranslatef(0.0,0.0,0.0);		//整体平移桌子
	glScalef(size/2, size/2, size/2);

//	glColor4f(1.0,1.0,1.0,1.0);
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, tex);
	glPushMatrix();	
		//-z
		glBegin(GL_POLYGON);              
			glTexCoord2f( 0.0, 0.0 ); glVertex3f( -

1.0, -1.0, -1.0 );
			glTexCoord2f( 1.0, 0.0 ); glVertex3f(  

1.0, -1.0, -1.0 );
			glTexCoord2f( 1.0, 1.0 ); glVertex3f(  

1.0,  1.0, -1.0 );
			glTexCoord2f( 0.0, 1.0 ); glVertex3f( -

1.0,  1.0, -1.0 );
		glEnd();
		//z
		glBegin(GL_POLYGON);              
			glTexCoord2f( 0.0, 0.0 ); glVertex3f( -

1.0, -1.0, 1.0 );
			glTexCoord2f( 1.0, 0.0 ); glVertex3f(  

1.0, -1.0, 1.0 );
			glTexCoord2f( 1.0, 1.0 ); glVertex3f(  

1.0,  1.0, 1.0 );
			glTexCoord2f( 0.0, 1.0 ); glVertex3f( -

1.0,  1.0, 1.0 );
		glEnd();
		//-y
		glBegin(GL_POLYGON);              
			glTexCoord2f( 0.0, 0.0 ); glVertex3f( -

1.0, -1.0, -1.0 );
			glTexCoord2f( 1.0, 0.0 ); glVertex3f(  

1.0, -1.0, -1.0 );
			glTexCoord2f( 1.0, 1.0 ); glVertex3f(  

1.0, -1.0,  1.0 );
			glTexCoord2f( 0.0, 1.0 ); glVertex3f( -

1.0, -1.0,  1.0 );
		glEnd();
		//y
		glBegin(GL_POLYGON);              
			glTexCoord2f( 0.0, 0.0 ); glVertex3f( -

1.0,  1.0, -1.0 );
			glTexCoord2f( 1.0, 0.0 ); glVertex3f(  

1.0,  1.0, -1.0 );
			glTexCoord2f( 1.0, 1.0 ); glVertex3f(  

1.0,  1.0,  1.0 );
			glTexCoord2f( 0.0, 1.0 ); glVertex3f( -

1.0,  1.0,  1.0 );
		glEnd();
		//-x
		glBegin(GL_POLYGON);              
			glTexCoord2f( 0.0, 0.0 ); glVertex3f( -

1.0, -1.0, -1.0 );
			glTexCoord2f( 1.0, 0.0 ); glVertex3f( -

1.0,  1.0, -1.0 );
			glTexCoord2f( 1.0, 1.0 ); glVertex3f( -

1.0,  1.0,  1.0 );
			glTexCoord2f( 0.0, 1.0 ); glVertex3f( -

1.0, -1.0,  1.0 );
		glEnd();
		//x
		glBegin(GL_POLYGON);              
			glTexCoord2f( 0.0, 0.0 ); glVertex3f(  

1.0, -1.0,-1.0 );
			glTexCoord2f( 1.0, 0.0 ); glVertex3f(  

1.0,  1.0,-1.0 );
			glTexCoord2f( 1.0, 1.0 ); glVertex3f(  

1.0,  1.0, 1.0 );
			glTexCoord2f( 0.0, 1.0 ); glVertex3f(  

1.0, -1.0, 1.0 );
		glEnd();
	glPopMatrix();
	glDisable(GL_TEXTURE_2D);
}

//贴图练习
void DrawMf(void){
	float xishu=1;		//贴图数量比例
	glRotatef(90.0, 1.0, 0.0, 0.0);
	glTranslatef(4.0,0.0,0.0 );
	glColor4f(0,0,0,1.0);
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, room_ground);
	glPushMatrix();	
		glBegin(GL_POLYGON);              
			glTexCoord2f( 0, 0.0 ); glVertex3f(  -

10.0,10.0, -10.0 );
			glTexCoord2f( xishu*1.0, 0.0 ); 

glVertex3f(  10.0,10.0, -10.0 );
			glTexCoord2f( xishu*1.0, xishu*1.0 ); 

glVertex3f(  10.0,10.0, 10.0 );
			glTexCoord2f( 0, xishu*1.0 ); glVertex3f(  

-10.0,10.0, 10.0 );
		glEnd();
	glPopMatrix();
	glDisable(GL_TEXTURE_2D);
}

//屋顶灯
void DrawLight(void){
	glPushMatrix();
			 glTranslatef(0,0,30);
			 glScalef(8, 8, 0.8);
			 glutSolidCube(1.0);	//测试灯光用的立方

体
	glPopMatrix();
}

//房间
void DrawRoom(void){
	//地面
	glPushMatrix();	
		glTranslatef(0.0,0.0,-3.0);		//整体平移
		glScalef(80,80,0.2);
		MyCube(1.0,room_ground);
	glPopMatrix();
	//墙
	//1右
	glPushMatrix();	
		glTranslatef(40.0,0.0,14.0);		//整体平移
		glScalef(0.2,80,35);
		MyCube(1.0,room_wall);
	glPopMatrix();
	//2左
	glPushMatrix();	
		glTranslatef(-40.0,0.0,14.0);		//整体平移
		glScalef(0.2,80,35);
		MyCube(1.0,room_wall);
	glPopMatrix();
/*	//3前
	glPushMatrix();	
		glTranslatef(0.0,-40,14.0);		//整体平移
		glScalef(80,0.2,35);
		MyCube(1.0,room_wall);
	glPopMatrix();
*/	//4后
	glPushMatrix();	
		glTranslatef(0.0,40,14.0);		//整体平移
		glScalef(80,0.2,35);
		MyCube(1.0,room_wall);
	glPopMatrix();
	//房顶
	glPushMatrix();	
		glTranslatef(0.0,0.0,30.0);		//整体平移
		glScalef(80,80,0.2);
		MyCube(1.0,room_up);
	glPopMatrix();
}

//椅子
void DrawChair(void){
//	glRotatef(90.0, 0.0, 0.0, 1.0);
//	glScalef(0.8, 0.8, 0.8);
//	glTranslatef(-6.0,0.0,-3.0);		//整体平移
	
	glPushMatrix();	
		
		//腿
//		glColor4f(1,1,1,1.0);
		//1
		glPushMatrix();
			glTranslatef(-1.5,-1.5,1.5);
			glScalef(0.2, 0.2, 6);
			MyCube(1.0,chair);
		glPopMatrix();

		//2
		glPushMatrix();
			glTranslatef(-1.5,1.5,1.5);
			glScalef(0.2, 0.2, 6);
			MyCube(1.0,chair);
		glPopMatrix();

		//3
		glPushMatrix();
			glTranslatef(1.5,1.5,0);
			glScalef(0.2, 0.2, 3);
			MyCube(1.0,chair);
		glPopMatrix();

		//4
		glPushMatrix();
			glTranslatef(1.5,-1.5,0);
			glScalef(0.2, 0.2, 3);
			MyCube(1.0,chair);
		glPopMatrix();

		//椅子面
		glPushMatrix();
//			glColor4f(0.6,1.0,0.0,1.0);
			glTranslatef(0.0,0.0,1.5);
			glScalef(3.4, 3.4, 0.2);
			MyCube(1.0,chair);
		glPopMatrix();

		//椅子靠背
		glPushMatrix();
			glTranslatef(-1.5,0.0,3.7);
			glScalef(0.1, 3.4, 1.5);
			MyCube(1.0,chair);
		glPopMatrix();

	glPopMatrix();	
}

//桌子
void DrawDesk(void){
	
	glPushMatrix();	
		//桌子腿
		glTranslatef(0.0,0.0,-3.0);
//		glColor4f(0.914,0.467,0.192,1.0);	//桌子腿的

颜色
		//1
		glPushMatrix();	
			glTranslatef(3.0,3.0,0.0);	
			glPushMatrix();
				/*参数1(1.0F)是圆柱体的底面半径

,参数2(1.0F)
				是圆柱体的饿顶面半径,参数3(3.0F

)是圆柱体的高度。
				参数4(32)是纬线(环绕Z轴有多少细

分),参数5(32)
				是经线(沿着Z轴有多少细分)*/
				gluCylinder(gluNewQuadric

(),0.5,0.2,3.0,20,20);
			glPopMatrix();
		glPopMatrix();	

		//2
		glPushMatrix();	
			glTranslatef(-3.0,3.0,0.0);	
			glPushMatrix();
				gluCylinder(gluNewQuadric

(),0.5,0.2,3.0,20,20);
			glPopMatrix();
		glPopMatrix();	

		//3
		glPushMatrix();	
			glTranslatef(-3.0,-3.0,0.0);	
			glPushMatrix();
				gluCylinder(gluNewQuadric

(),0.5,0.2,3.0,20,20);
			glPopMatrix();
		glPopMatrix();	

		//4
		glPushMatrix();	
			glTranslatef(3.0,-3.0,0.0);	
			glPushMatrix();
				gluCylinder(gluNewQuadric

(),0.5,0.2,3.0,20,20);
			glPopMatrix();
		glPopMatrix();	

		//桌子面
		glTranslatef(0.0,0.0,3.0);
//		glColor4f(0.0,1.0,0.8,1.0);
		glPushMatrix();
			glScalef (8.0, 8.0, 0.2);
			MyCube(1.0,desk);
		glPopMatrix();
				
	glPopMatrix();	
}

//画花瓶
//用四边形带画花瓶的一层,该层上底面圆心坐标为(x,y,z),上底面

圆的半径为radius_up,下底面圆的半径为radius_down,M表示圆周的被分

成多少份,yy_down代表下圆面y值
void DrawVase_one(GLfloat xx, GLfloat yy_up, GLfloat zz, GLfloat 

radius_up, GLfloat radius_down, GLfloat M, GLfloat yy_down, 

GLfloat tt,GLfloat VaseN,GLint tex){
	float step_z = 2*PI/M;	//角度步长
	float x[4],y[4],z[4];
	float angle_z = 0.0;	//角度
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, tex);

	glBegin(GL_QUADS);
		 for(float i=0; i<M; i++)
		{
			angle_z = i * step_z;

			x[0] = radius_up * sin(angle_z);
			y[0] = yy_up;
			z[0] = radius_up * cos(angle_z);

			x[1] = radius_up * sin(angle_z + step_z);
			y[1] = yy_up;
			z[1] = radius_up * cos(angle_z + step_z);

			x[2] = radius_down * sin(angle_z + 

step_z);
			y[2] = yy_down;
			z[2] = radius_down * cos(angle_z + 

step_z);

			x[3] = radius_down * sin(angle_z);
			y[3] = yy_down;
			z[3] = radius_down * cos(angle_z);

			glTexCoord2f( i/M, 1-tt/VaseN );		

	glVertex3f(xx+x[0], yy_up+y[0],zz+z[0]);
			glTexCoord2f( (i+1)/M, 1-tt/VaseN );     	

glVertex3f(xx+x[1], yy_up+y[1],zz+z[1]);
			glTexCoord2f( (i+1)/M, 1-(tt+1)/VaseN );	

glVertex3f(xx+x[2], yy_up+y[2],zz+z[2]);
			glTexCoord2f( i/M, 1-(tt+1)/VaseN );		

glVertex3f(xx+x[3], yy_up+y[3],zz+z[3]);
		 }
	glEnd();
	glDisable(GL_TEXTURE_2D);
}

//花瓶
void DrawVase(void){
	float Hight=3;		//花瓶高度
	float VaseY_0;
	int VaseN=30;			//花瓶竖直方向细分数
	float hh;				//Y方向步长
	float radius_down;
	float radius_up;
	
	VaseY_0=Hight/2;
	hh=Hight/VaseN;
	radius_down=VaseY_0;

	

	glPushMatrix();
		glTranslatef(8.0,0,5.5);
		glRotatef(90, 1.0, 0.0, 0.0);
	//	glColor4f(1,1,1,1.0);
		glScalef(0.7, 0.8, 0.7);

		for(int tt=0;tt < VaseN;tt++){
			radius_up=radius_down;
			radius_down=VaseY_0-hh*(tt+1);
			DrawVase_one(0,radius_up,0,0.7*sinf(2*PI*

(1-hh*tt/Hight))+1.1,0.7*sinf(2*PI*(1-hh*(tt

+1)/Hight))+1.1,200,radius_down-hh,tt,VaseN,vase);
		}
	glPopMatrix();
}

//地球仪
void DrawMap(void){
	float Hight=3;			//球体高度
	float VaseY_0;
	int VaseN=30;			//球体竖直方向细分数
	float hh;				//Y方向步长
	float radius_down;
	float radius_up;
	
	VaseY_0=Hight/2;
	hh=Hight/VaseN;
	radius_down=VaseY_0;

	
	glPushMatrix();
		
		glRotatef(90.0, 1.0, 0.0, 0.0);
		glTranslatef(4.0,0.8,-3.0);
		glScalef(0.5, 0.5, 0.5);
		//画球体
		glPushMatrix();
	//		glColor4f(1,1,1,1.0);
			glScalef(1, 1, 1);
			glRotatef(45.0, 0.0, 1.0, 0.0);
			glTranslatef(0.0,9.0,0.0);
			for(int tt=0;tt < VaseN;tt++){
				radius_up=radius_down;
				radius_down=VaseY_0-hh*(tt+1);
				DrawVase_one(0,radius_up,0,sqrtf

(pow(Hight,2)-pow((2*Hight*(1-hh*tt/Hight)-Hight),2)),sqrtf(pow

(Hight,2)-pow((2*Hight*(1-hh*(tt+1)/Hight)-

Hight),2)),200,radius_down-hh,tt,VaseN,map);
			}
		glPopMatrix();

		//底座
		glPushMatrix();
			glScalef(1.2, 0.8, 1.2);
			glRotatef(0.0, 0.0, 1.0, 0.0);
			glTranslatef(-0.0,5.0,-0.0);
	//		glColor4f(1,1,1,1.0);
			DrawVase_one(0,1,0,0,2,200,0,1,1,dizuo);
		glPopMatrix();

		//轴
		glPushMatrix();
			glScalef(1, 1, 1);
			glRotatef(0.0, 0.0, 1.0, 0.0);
			glTranslatef(-0.0,0.0,0.0);
	//		glColor4f(1,1,1,1.0);
			DrawVase_one

(0,5,0,0.1,0.1,100,0,1,1,dizuo);
		glPopMatrix();
	glPopMatrix();
}



//导入OBJ文件函数
vector<glm::vec3> vertices;  
vector<glm::vec2> uvs;  
vector<glm::vec3> normals;  
int nodesSize;
bool loadOBJ(
        const char * path,
        std::vector<glm::vec3> & out_vertices,
        std::vector<glm::vec2> & out_uvs,
        std::vector<glm::vec3> & out_normals
){
        printf("Loading OBJ file %s...\n", path);

        std::vector<unsigned int> vertexIndices, uvIndices, 

normalIndices;
        std::vector<glm::vec3> temp_vertices;
        std::vector<glm::vec2> temp_uvs;
        std::vector<glm::vec3> temp_normals;


        FILE * file = fopen(path, "r");
        if( file == NULL ){
                printf("Impossible to open the file ! Are you in 

the right path ? See Tutorial 1 for details\n");
                return false;
        }

        while( 1 ){

                char lineHeader[128];
                // read the first word of the line
                int res = fscanf(file, "%s", lineHeader);
                if (res == EOF)
                        break; // EOF = End Of File. Quit the 

loop.

                // else : parse lineHeader

                if ( strcmp( lineHeader, "v" ) == 0 ){
                    //cout<<"Get v"<<endl;
                        glm::vec3 vertex;
                        fscanf(file, "%f %f %f\n", &vertex.x, 

&vertex.y, &vertex.z );
                        temp_vertices.push_back(vertex);
                }else if ( strcmp( lineHeader, "vt" ) == 0 ){
                    //cout<<"Get vt"<<endl;
                        glm::vec2 uv;
                        fscanf(file, "%f %f\n", &uv.x, &uv.y );
                        uv.y = -uv.y; // Invert V coordinate since 

we will only use DDS texture, which are inverted. Remove if you 

want to use TGA or BMP loaders.
                        temp_uvs.push_back(uv);
                }else if ( strcmp( lineHeader, "vn" ) == 0 ){
                    //cout<<"Get vn"<<endl;
                        glm::vec3 normal;
                        fscanf(file, "%f %f %f\n", &normal.x, 

&normal.y, &normal.z );
                        temp_normals.push_back(normal);
                }else if ( strcmp( lineHeader, "f" ) == 0 ){
                    //cout<<"Get f"<<endl;
                        std::string vertex1, vertex2, vertex3;
                        unsigned int vertexIndex[3], uvIndex[3], 

normalIndex[3];
                        int matches = fscanf(file, "%d//%d %d//%d 

%d//%d\n", &vertexIndex[0], &normalIndex[0], &vertexIndex[1], 

&normalIndex[1], &vertexIndex[2], &normalIndex[2]);  
                        if (matches != 6){  
                                printf("File can't be read by our 

simple parser :-( Try exporting with other options\n");  
                                return false;  
                        }  
                        vertexIndices.push_back(vertexIndex[0]);  
                        vertexIndices.push_back(vertexIndex[1]);  
                        vertexIndices.push_back(vertexIndex[2]);  
                        normalIndices.push_back(normalIndex[0]);  
                        normalIndices.push_back(normalIndex[1]);  
                        normalIndices.push_back(normalIndex[2]);  
                }else{
                        // Probably a comment, eat up the rest of 

the line
                        char stupidBuffer[1000];
                        fgets(stupidBuffer, 1000, file);
                }


        }

        // For each vertex of each triangle
        for( unsigned int i=0; i<vertexIndices.size(); i++ ){

                // Get the indices of its attributes
                unsigned int vertexIndex = vertexIndices[i];
                unsigned int normalIndex = normalIndices[i];

                // Get the attributes thanks to the index
                glm::vec3 vertex = temp_vertices[ vertexIndex-1 ];
                glm::vec3 normal = temp_normals[ normalIndex-1 ];

                // Put the attributes in buffers
                out_vertices.push_back(vertex);
                out_normals .push_back(normal);

        }

        return true;
}

//画龙
void DrawDragon(void){
	 glPushMatrix();
	  glTranslatef(4,-3,4);
	  glRotated(0,0,0,1);
	  glRotated(90,1,0,0);
	  glScalef(2.0,2.0,2.0);
	  int i;
		glBegin(GL_TRIANGLES);  
			for(i = 0; i<nodesSize; i++)  
			{  
			glNormal3f(normals[i].x, normals[i].y, 

normals[i].z);  
			glVertex3f( vertices[i].x, vertices[i].y, 

vertices[i].z);  
		}  
		glEnd();  
	glPopMatrix();
}


//实现场景漫游
void WalkMan(void){
	rad = float(PI*s_angle / 180.0f);                    //计

算SIN和COS函数中需要的参数。
	// 观察点
	s_at[0] = float(s_eye[0] + 100 * cos(rad));
	s_at[2] = float(s_eye[2] + 100 * sin(rad));
	s_at[1] = s_eye[1];
	//观察点可以设置的更远一些,如果设置的更小可能导致不能看到

较远的物体,也是通过sin和cos函数实现
	//向前进方向去设置观察点。
	// 设置观察点
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(s_eye[0], s_eye[1], s_eye[2],
		s_at[0], s_at[1], s_at[2],
		0.0, 1.0, 0.0);
}

//阴影
void pointSourceShadow( double lx, double ly, double lz,
     double a, double b, double c, double d, GLfloat M[16]) {
     double new_d = d + (a * lx + b * ly + c * lz);
     M[0] = 1;            M[4] = 0;            M[8] = 0;           

  M[12] = 0;
     M[1] = 0;            M[5] = 1;            M[9] = 0;           

  M[13] = 0;
     M[2] = 0;            M[6] = 0;            M[10] = 1;		

	 M[14] = 0;
     M[3]= -a/new_d;  M[7]= -b/new_d;  M[11]= -c/new_d;  M[15] = 

0;

}


void myDisplay(void)
{
	GLfloat position0[]={position_light[0],position_light

[1],position_light[2],0};		//光源位置,最后一位  0:

光源类型为方向光
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glPushMatrix();
		WalkMan();		//通过改变摄像机的位置来实

现场景漫游
		//绘制立方体
		glColor4f(1.0,1.0,1.0,1.0);
		glRotatef(RdegreeZ, 0.0, 1.0, 0.0);
		glRotatef(RdegreeX, 1.0, 0.0, 0.0);
		glColor4f(1.0,1.0,1.0,1.0);
		glRotatef(-90.0, 1.0, 0.0, 0.0);
		glTranslatef(-5.0,0.0,-5.0);		//整体平移

桌子
		DrawDesk();			//桌子
		glColor4f(1.0,1.0,1.0,1.0);
		glRotatef(90.0, 0.0, 0.0, 1.0);
		glScalef(0.8, 0.8, 0.8);
		glTranslatef(-6.0,0.0,-3.0);		//整体平移
		DrawChair();		//椅子
		glColor4f(1.0,1.0,1.0,1.0);
		DrawRoom();			//房间
		glColor4f(1.0,1.0,1.0,1.0);
		DrawMap();			//地球仪
		glColor4f(1,0,0,1.0);
		DrawDragon();		//画龙
		glColor4f(1.0,1.0,1.0,1.0);
		DrawVase();			//花瓶
		glColor4f(1.0,1.0,1.0,1.0);
		DrawLight();		//屋顶灯

		glPushMatrix();
			 glTranslatef(position_light

[0],position_light[1],position_light[2]);
			 glRotated(0,0,0,0);
			 glutSolidCube(1.0);	//测试灯光用的立方

体
		glPopMatrix();
	
		//阴影
		GLfloat M[16];
		double light_x = position_light[0], light_y = 

position_light[1],light_z = position_light[2];
		glPushMatrix();

		glPushMatrix();
			glDisable( GL_LIGHTING);
			glDisable(GL_LIGHT0); 
			glColor4f( 0.2, 0.2, 0.2, 0.3);
			//glMatrixMode(GL_MODELVIEW);
			//glLoadIdentity();
			glTranslatef( light_x, light_y, light_z);
			pointSourceShadow( light_x, light_y, 

light_z, 0, 0, 1, -3.2, M);            
			glMultMatrixf( M);
			glTranslatef( -light_x, -light_y, -

light_z);

			DrawMap();			//地球仪
			DrawVase();			//花瓶
			DrawDragon();		//画龙

		glPopMatrix();

		
		//glPushMatrix();
		//	glDisable( GL_LIGHTING);
		//	glDisable(GL_LIGHT0); 
		//	glColor4f( 0, 0, 0, 1);
		//	//glMatrixMode(GL_MODELVIEW);
		//	//glLoadIdentity();
		//	glTranslatef( light_x, light_y, light_z);
		//	pointSourceShadow( light_x, light_y, 

light_z, 0, 0, 1, 2.5, M);            
		//	glMultMatrixf( M);
		//	glTranslatef( -light_x, -light_y, -

light_z);
		//	glPushMatrix();
		//		DrawDesk();			//

桌子
		//	glPopMatrix();
		//		DrawChair();		//椅子

		//glPopMatrix();

		glPopMatrix();

		glEnable(GL_LIGHTING); //启用光源
		glEnable(GL_LIGHT0);   //使用指定灯光

	glLightfv(GL_LIGHT0,GL_POSITION,position0);		//

设置光源位置
	printf("x=%f \t",position_light[0]); printf("y=%f 

\t",position_light[1]); printf("z=%f \n",position_light[2]);	//

输出灯光位置
	glPopMatrix();
	glutSwapBuffers();//双缓存刷新
}

//贴图
GLint load_texture(const char *file_name)
{
	FILE* pFile = fopen(file_name, "rb"); //读取图片
	if( pFile == 0 ) {return 0;}
	fseek(pFile, 0x0012, SEEK_SET);//移动到0x0012位置
	fread(&w, 4, 1, pFile);//读取宽度
	fread(&h, 4, 1, pFile);//读取高度
	fseek(pFile, BMP_Header_Length, SEEK_SET);//跳过BMP头部的

54个字节,这些字节我们不用
	GLuint line_bytes = w * 3;//BMP里一个像素3字节 
	while( line_bytes % 4 != 0 ) {++line_bytes;}//补齐成4的倍

数
	total_bytes = line_bytes * h;
	pixels = (GLbyte*)malloc(total_bytes);//分配内存
	if( pixels == 0 ) 
	{
		fclose(pFile); return 0; 
	}
	if( fread(pixels, total_bytes, 1, pFile) <= 0 ) { free

(pixels); fclose(pFile); return 0; }
	glGenTextures(1, &texture_ID);//创建新纹理并标记
	if( texture_ID == 0 ) { free(pixels); fclose(pFile); 

return 0; }
	glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture_ID);
	glBindTexture(GL_TEXTURE_2D, texture_ID);
	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);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 

GL_REPEAT);
	GLfloat blend[] = {1.0,1.0,1.0,1.0};
	glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, blend);//

最后一个参数必须为GL_BLEND才能实现光照和纹理融合
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, 

GL_BGR_EXT, GL_UNSIGNED_BYTE, pixels);
	glBindTexture(GL_TEXTURE_2D, last_texture_ID);
	free(pixels);//释放内存
	return texture_ID;
}

//鼠标事件
void Mouse(int button, int state, int x, int y) //处理鼠标点击  
{  
    if(state==GLUT_DOWN){ //第一次鼠标按下时,记录鼠标在窗口中的初

始坐标  
        oldmx=x,oldmy=y;  
		printf("%s \n", "this is mouse");
	}
}  
//鼠标移动事件	
void onMouseMove(int x,int y) //处理鼠标拖动  
{  
	s_angle += (x-oldmx);  
    oldmx=x,oldmy=y; //把此时的鼠标坐标作为旧值,为下一次计算增量

做准备  
	glutPostRedisplay();
}  

//键盘控制
void keyboard(unsigned char key, int x, int y){
	switch (key)
	{
	case'q':
	//	printf("%s \n", "this is Q");
		position_light[0]-=1;
		//如果按上方向键,沿着转换角度后的方向前进,speed

为每次前进的步长,通过sin和cos函数实现沿着现
		//有角度方向前进。
		glutPostRedisplay();
		break;
	case'w':
	//	printf("%s \n", "this is W");
		position_light[0]+=1;
		//如果按上方向键,沿着转换角度后的方向前进,speed

为每次前进的步长,通过sin和cos函数实现沿着现
		//有角度方向前进。
		glutPostRedisplay();
		break;
	case's':
	//	printf("%s \n", "this is S");
		position_light[1]+=1;
		//如果按上方向键,沿着转换角度后的方向前进,speed

为每次前进的步长,通过sin和cos函数实现沿着现
		//有角度方向前进。
		glutPostRedisplay();
		break;
	case'a':
	//	printf("%s \n", "this is A");
		position_light[1]-=1;
		glutPostRedisplay();
		break;
	case'd':
		printf("%s \n", "this is D");
		glutPostRedisplay();
		break;
	case'z':
	//	printf("%s \n", "this is Z");
		position_light[2]-=1;
		glutPostRedisplay();
		break;
	case'x':
	//	printf("%s \n", "this is X");
		position_light[2]+=1;
		glutPostRedisplay();
		break;
	default:
		break;
	}
}

//键盘方向键控制
void mySpecial(int key, int x, int y){
	switch (key)
	{
	case GLUT_KEY_UP:
	//	printf("%s \n", "this is up");
//		RdegreeX += 5.0;
		s_eye[2] += (float)sin(rad) * speed;
		s_eye[0] += (float)cos(rad) * speed;
		//如果按上方向键,沿着转换角度后的方向前进,speed

为每次前进的步长,通过sin和cos函数实现沿着现
		//有角度方向前进。
		glutPostRedisplay();
		break;

	case GLUT_KEY_DOWN:
	//	printf("%s \n", "this is down");
//		RdegreeX -= 5.0;
		s_eye[2] -= (float)sin(rad) * speed;
		s_eye[0] -= (float)cos(rad) * speed;
		//如果按下方向键,沿着转换角度后的方向后退,speed

为每次前进的步长,通过sin和cos函数实现沿着现
		//有角度方向前进。
		glutPostRedisplay();
		break;

	case GLUT_KEY_LEFT:
	//	printf("%s \n", "this is left");
//		RdegreeZ += 5.0;
		s_angle -= 2.0;                        //每按一次

左键,旋转2度。
		glutPostRedisplay();
		break;

	case GLUT_KEY_RIGHT:
	//	printf("%s \n", "this is right");
//		RdegreeZ -= 5.0;
		s_angle += 2.0;                       //每按一次右

键,旋转2度。
		glutPostRedisplay();
		break;
	}
}

//初始化函数
void init(){
	//更改清屏颜色
	glClearColor(0.0, 0.0, 0.0, 0.0);//黑色
	glClearDepth(1.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(75,1,0.1,1000);	//视景体(摄像机)参数:60

度+长宽比=1+近点=1+远点=100
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	WalkMan();
	glEnable(GL_DEPTH_TEST);		//隐藏面消除
	//贴图图片
	room_ground = load_texture("地板.bmp"); 
	room_wall= load_texture("墙.bmp"); 
	room_up=load_texture("屋顶.bmp"); 
	desk= load_texture("木纹_桌子.bmp"); 
	chair= load_texture("木纹_椅子.bmp"); 
	map= load_texture("地图.bmp"); 
	vase= load_texture("花瓶.bmp"); 
	dizuo=load_texture("底座.bmp"); 

	//材质
	GLfloat diffuseMaterial[]={0.5,0.5,0.5,1.0};
	GLfloat mat_specular[]={1.0,1.0,1.0,1.0};
	glMaterialfv(GL_FRONT,GL_DIFFUSE,diffuseMaterial);
	glMaterialfv(GL_FRONT,GL_SPECULAR,mat_specular);
	glMaterialf(GL_FRONT,GL_SHININESS,25.0);
	glEnable(GL_COLOR_MATERIAL);	//启动颜色追踪

	//灯光
	glShadeModel(GL_SMOOTH);			

//GL_SMOOTH:光滑明暗处理
	//glEnable(GL_BLEND);					//

启用颜色混合
	//设置普通灯光照0位置及参数
	GLfloat position0[]={position_light[0],position_light

[1],position_light[2],1};	
	/*光源位置,最后一位  0:方向光(线光源)  1:无方向(点光源

)
	position的第四个分量如果是0,那么光源就是directional的,

postion值实际是一个向量;
	否则这个光源就是postional,position就是他的位置。光源的位

置和方向都会受ModelView Matrix的影响。*/

	GLfloat light0s[]={1,1,1,1};		//RGBA下的镜面光
	GLfloat light0d[]={1,1,1,1};		//RGBA下的漫反射光
	GLfloat light0a[]={1,1,1,1};		//RGBA下的环境光
	GLfloat light_Model_Ambient[]={0.2,0.2,0.2,1.0};

	glLightModelfv( GL_LIGHT_MODEL_AMBIENT , 

light_Model_Ambient ); //设置全局环境光的方法
	glLightfv(GL_LIGHT0,GL_POSITION,position0);		//

设置光源位置
	glLightfv(GL_LIGHT0,GL_SPECULAR,light0s);
	glLightfv(GL_LIGHT0,GL_DIFFUSE,light0d);
	glLightfv(GL_LIGHT0,GL_AMBIENT,light0a);
	//聚光灯参数设置
	//glLightf( GL_LIGHT0,GL_SPOT_CUTOFF , 45.0 );		//

灯锥张角
	//GLfloat spot_direction[]={ 0.0 , 0.0 , -1.0 };		

//聚光灯朝向
	//glLightfv( GL_LIGHT0 , GL_SPOT_DIRECTION , 

spot_direction );
	//glLightf( GL_LIGHT0 , GL_SPOT_EXPONENT , 0 );	//设置聚光

指数 聚光指数控制光的集中程度,光锥中心的光强最大,越靠边的光强越

小。缺省时为0,即均匀照射。

	glEnable(GL_LIGHTING); //启用光源
	glEnable(GL_LIGHT0);   //使用指定灯光
//	glDisable(GL_LIGHTING); //关闭光源
}

int main(int argc, char *argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
	glutInitWindowPosition(300, 50);
	glutInitWindowSize(600, 600);
	glutCreateWindow("hp_CG_03_三维场景");
	init();
	glutDisplayFunc(&myDisplay);
	glutKeyboardFunc(keyboard);
	glutMouseFunc(Mouse);  
	glutMotionFunc(onMouseMove);  
	glutSpecialFunc(mySpecial);

	//导入OBJ文件
	bool res = loadOBJ("dragon.obj", vertices, uvs, normals);  
    cout<<vertices.size()<<endl;  
	nodesSize = vertices.size();

	glutMainLoop();
	return 0;

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值