1. 程式人生 > >VS2012下基於Glut glRotatef glTranslatef示例程式:

VS2012下基於Glut glRotatef glTranslatef示例程式:

Demo使用glRotatef ,glTranslatef來實現一個太陽、地球、月亮運動的3D圖形。

1.glTranslatef() ——模型變換函式 移動

void glTranslatef(GLfloat  x,  GLfloat  y,  GLfloat  z);

這個函式表示模型是怎樣移動的。舉個例子:

glTranslatef(-1.0,0.0,-2.0);//表示物體沿x負方向移動1.0,沿z軸負方向移動2.0。

2.glRotatef()——模型變換函式  旋轉

void glRotatef(GLfloat  angle,  GLfloat  x,  GLfloat  y

,  GLfloat  z);

angle表示旋轉的角度(注意單位不是弧度),(x,y,z)表示轉軸。舉個例子:

glRotatef(45.0, 0.0, 0.0, 1.0);//表示模型沿著(0,0,1)這個軸旋轉45°。

3.glPerspective() ——投影變換函式 透視投影

void gluPerspective(GLdouble  fovy,  GLdouble  aspect,  GLdouble  zNear,  GLdouble  zFar);

glPerspective函式的相關引數代表的意義參看下圖:

fovy視角寬度

aspect:w/h


平移、旋轉、以及縮放效果:

正交投影以及透視投影:


正交投影下顯示效果:


右擊滑鼠右鍵選單選擇是否顯示座標軸以及透視和正交投影模式:


透視投影:


原始碼:

// GlutSolarDemo.cpp : 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include <gl/glut.h>
#include <math.h>
//圓周率巨集
#define GL_PI 3.1415f
//獲取螢幕的寬度
GLint SCREEN_WIDTH=0;
GLint SCREEN_HEIGHT=0;
//設定程式的視窗大小
GLint windowWidth=400;
GLint windowHeight=300;
//繞x軸旋轉角度
GLfloat xRotAngle=0.0f;
//繞y軸旋轉角度
GLfloat yRotAngle=0.0f;
//受支援的點大小範圍
GLfloat sizes[2];
//受支援的點大小增量
GLfloat step;
//最大的投影矩陣堆疊深度
GLint iMaxProjectionStackDepth;
//最大的模型檢視矩陣堆疊深度
GLint iMaxModeviewStackDepth;
//最大的紋理矩陣堆疊深度
GLint iMaxTextureStackDepth;

GLfloat  whiteLight[] = { 0.4f, 0.4f, 0.4f, 1.0f };
GLfloat  sourceLight[] = { 0.8f, 0.8f, 0.8f, 1.0f };
GLfloat	 lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };

GLint iCoordinateaxis=2;
GLint iProjectionMode=1;
void changSize(GLint w,GLint h);
//選單回撥函式
void processMenu(int value){
	switch(value){
		case 1:
			iCoordinateaxis=1;
			break;
		case 2:
			iCoordinateaxis=2;
			break;
		case 3:
			iProjectionMode=1;
			//強制呼叫視窗大小變化回撥函式,更改投影模式為正交投影
			changSize(glutGet(GLUT_WINDOW_WIDTH),glutGet(GLUT_WINDOW_HEIGHT));
			break;
		case 4:
			iProjectionMode=2;
			//強制呼叫視窗大小變化回撥函式,更改投影模式為透視投影
			changSize(glutGet(GLUT_WINDOW_WIDTH),glutGet(GLUT_WINDOW_HEIGHT));
			break;
		default:
			break;
	}
	//重新繪製
	glutPostRedisplay();
}
//顯示回撥函式
void renderScreen(void){
	static float fMoonRot = 0.0f;
	static float fEarthRot = 0.0f;
	//將視窗顏色清理為黑色
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    //把整個視窗清理為當前清理顏色:黑色;清除深度緩衝區。
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    //將當前Matrix狀態入棧
    glPushMatrix();
	if(2==iProjectionMode)
		glTranslatef(0.0f, 0.0f, -250.0f);	//透視投影為便於觀察整個座標系往內移動250個單位
    //座標系繞x軸旋轉xRotAngle
    glRotatef(xRotAngle,1.0f,0.0f,0.0f);
    //座標系繞y軸旋轉yRotAngle
    glRotatef(yRotAngle,0.0f,1.0f,0.0f);
	//進行平滑處理 
	glEnable(GL_POINT_SMOOTH);
	glHint(GL_POINT_SMOOTH,GL_NICEST);
	glEnable(GL_LINE_SMOOTH);
	glHint(GL_LINE_SMOOTH,GL_NICEST);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

	//白色繪製座標系
	if(1==iCoordinateaxis){
		glColor3f(1.0f,1.0f,1.0f);
		glBegin(GL_LINES);
			glVertex3f(-90.0f,00.0f,0.0f);
			glVertex3f(90.0f,0.0f,0.0f);
			glVertex3f(0.0f,-90.0f,0.0f);
			glVertex3f(0.0f,90.0f,0.0f);
			glVertex3f(0.0f,0.0f,-90.0f);
			glVertex3f(0.0f,0.0f,90.0f);
		glEnd();

		glPushMatrix();
		glTranslatef(90.0f,0.0f,0.0f);
		glRotatef(90.0f,0.0f,1.0f,0.0f);
		glutSolidCone(3,6,10,10);
		glPopMatrix();

		glPushMatrix();
		glTranslatef(0.0f,90.0f,0.0f);
		glRotatef(-90.0f,1.0f,0.0f,0.0f);
		glutSolidCone(3,6,10,10);
		glPopMatrix();

		glPushMatrix();
		glTranslatef(0.0f,0.0f,90.0f);
		glRotatef(70.0f,0.0f,0.0f,1.0f);
		glutSolidCone(3,6,10,10);
		glPopMatrix();
	}

	glPushMatrix();

	glDisable(GL_LIGHTING);
	//Draw sun at(0.0f,0.0f,0.0f)
	glColor3ub(255, 255, 0);
	glutSolidSphere(15.0f, 30, 17);
	glEnable(GL_LIGHTING);

	//Move the light after we draw the sun!
	glLightfv(GL_LIGHT0,GL_POSITION,lightPos);

	//Rotate coordinate system
	glColor3ub(0,0,255);
	glRotatef(fEarthRot, 0.0f, 1.0f, 0.0f);
	fEarthRot += 5.0f;
	if(fEarthRot > 360.0f)
		fEarthRot = 0.0f;
	glTranslatef(105.0f,0.0f,0.0f);
	//Draw the Earth
	glutSolidSphere(15.0f, 30, 17);

	//Rotate from Earth based coordinates and draw Moon
	glColor3ub(200,200,200);
	glRotatef(fMoonRot,0.0f, 1.0f, 0.0f);
	fMoonRot+= 15.0f;
	if(fMoonRot > 360.0f)
		fMoonRot = 0.0f;
	glTranslatef(30.0f, 0.0f, 0.0f);
	glutSolidSphere(6.0f, 30, 17);

	glPopMatrix();


    //恢復壓入棧的Matrix
    glPopMatrix();
    //交換兩個緩衝區的指標
    glutSwapBuffers();
}
//設定Redering State 
void setupRederingState(void){
	
	// Enable lighting
    glEnable(GL_LIGHTING);
    // Setup and enable light 0
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT,whiteLight);
    glLightfv(GL_LIGHT0,GL_DIFFUSE,sourceLight);
    glLightfv(GL_LIGHT0,GL_POSITION,lightPos);
    glEnable(GL_LIGHT0);
    // Enable color tracking
    glEnable(GL_COLOR_MATERIAL);
    // Set Material properties to follow glColor values
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
	
    glEnable(GL_DEPTH_TEST);	//使能深度測試
    glFrontFace(GL_CCW);		//多邊形正面為逆時針方向
    glEnable(GL_CULL_FACE);		//不顯示背面

    //設定清理顏色為黑色
    glClearColor(0.0f,0.0,0.0,1.0f);
    //設定繪畫顏色為綠色
    glColor3f(1.0f,1.0f,0.0f);
	//使能深度測試
	glEnable(GL_DEPTH_TEST);
	//獲取受支援的點大小範圍
	glGetFloatv(GL_POINT_SIZE_RANGE,sizes);
	//獲取受支援的點大小增量
	glGetFloatv(GL_POINT_SIZE_GRANULARITY,&step);
	//獲取最大的投影矩陣堆疊深度
	glGetIntegerv( GL_MAX_PROJECTION_STACK_DEPTH,&iMaxProjectionStackDepth);
	//獲取最大的模型檢視矩陣堆疊深度
	glGetIntegerv( GL_MAX_MODELVIEW_STACK_DEPTH,&iMaxModeviewStackDepth);
	//獲取最大的紋理矩陣堆疊深度
	glGetIntegerv( GL_MAX_TEXTURE_STACK_DEPTH,&iMaxTextureStackDepth);
	printf("point size range:%f-%f\n",sizes[0],sizes[1]);
	printf("point step:%f\n",step);
	printf("iMaxProjectionStackDepth=%d\n",iMaxProjectionStackDepth);
	printf("iMaxModeviewStackDepth=%d\n",iMaxModeviewStackDepth);
	printf("iMaxTextureStackDepth=%d\n",iMaxTextureStackDepth);
}
//視窗大小變化回撥函式
void changSize(GLint w,GLint h){
    //橫寬比率
    GLfloat ratio;
    //設定座標系為x(-100.0f,100.0f)、y(-100.0f,100.0f)、z(-100.0f,100.0f)
    GLfloat coordinatesize=120.0f;
    //視窗寬高為零直接返回
    if((w==0)||(h==0))
        return;
    //設定視口和視窗大小一致
    glViewport(0,0,w,h);
    //對投影矩陣應用隨後的矩陣操作
    glMatrixMode(GL_PROJECTION);
    //重置當前指定的矩陣為單位矩陣 
    glLoadIdentity();
    ratio=(GLfloat)w/(GLfloat)h;
    //正交投影
	if(1==iProjectionMode){
		printf("glOrtho\n");
		if(w<h)
			glOrtho(-coordinatesize,coordinatesize,-coordinatesize/ratio,coordinatesize/ratio,-coordinatesize*2.0f,coordinatesize*2.0f);
		else
			glOrtho(-coordinatesize*ratio,coordinatesize*ratio,-coordinatesize,coordinatesize,-coordinatesize*2.0f,coordinatesize*2.0f);
		//當前矩陣設定為模型檢視矩陣
		glMatrixMode(GL_MODELVIEW);
		//重置當前指定的矩陣為單位矩陣 
		glLoadIdentity();
	}
	else{
		printf("gluPerspective\n");
		gluPerspective(45,ratio,10.0f,500.0f);
		//當前矩陣設定為模型檢視矩陣
		glMatrixMode(GL_MODELVIEW);
		//重置當前指定的矩陣為單位矩陣 
		glLoadIdentity();
	}

}

//按鍵輸入處理回撥函式
void specialKey(int key,int x,int y){

    if(key==GLUT_KEY_UP){
        xRotAngle-=5.0f;
    }
    else if(key==GLUT_KEY_DOWN){
        xRotAngle+=5.0f;
    }
    else if(key==GLUT_KEY_LEFT){
        yRotAngle-=5.0f;
    }
    else if(key==GLUT_KEY_RIGHT){
        yRotAngle+=5.0f;
    }
    //重新繪製
    glutPostRedisplay();
}

void timerFunc(int value)
{
	glutPostRedisplay();
	glutTimerFunc(100, timerFunc, 1);
}

int main(int argc, char* argv[])
{
	//選單
	GLint iMainMenu;
	GLint iCoordinateaxisMenu;
	GLint iOrthoOrPerspectMenu;
	//初始化glut 
    glutInit(&argc,argv);
    //使用雙緩衝區、深度緩衝區。
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA|GLUT_DEPTH);
    //獲取系統的寬畫素
    SCREEN_WIDTH=glutGet(GLUT_SCREEN_WIDTH);
    //獲取系統的高畫素
    SCREEN_HEIGHT=glutGet(GLUT_SCREEN_HEIGHT);
	//建立視窗,視窗名字為OpenGL Solar Demo
    glutCreateWindow("OpenGL Solar Demo");
    //設定視窗大小
    glutReshapeWindow(windowWidth,windowHeight);
    //視窗居中顯示
    glutPositionWindow((SCREEN_WIDTH-windowWidth)/2,(SCREEN_HEIGHT-windowHeight)/2);
    //視窗大小變化時的處理函式
    glutReshapeFunc(changSize);
    //設定顯示回撥函式 
    glutDisplayFunc(renderScreen);
    //設定按鍵輸入處理回撥函式
    glutSpecialFunc(specialKey);
	//選單回撥函式
	iCoordinateaxisMenu=glutCreateMenu(processMenu);
	//新增選單
	glutAddMenuEntry("Display coordinate axis",1);
	glutAddMenuEntry("Don't dispaly coordinate axis",2);
	iOrthoOrPerspectMenu=glutCreateMenu(processMenu);
	glutAddMenuEntry("Ortho",3);
	glutAddMenuEntry("Perspect",4);
	iMainMenu=glutCreateMenu(processMenu);
	glutAddSubMenu("Display or hide coordinate axis",iCoordinateaxisMenu);
	glutAddSubMenu("Ortho Or Perspect",iOrthoOrPerspectMenu);
	//將選單榜定到滑鼠右鍵上
	glutAttachMenu(GLUT_RIGHT_BUTTON);
	glutTimerFunc(250,timerFunc, 1);
    //設定全域性渲染引數
    setupRederingState();
    glutMainLoop();
    return 0;
}