VS2012下基於Glut glRotatef glTranslatef示例程式:
阿新 • • 發佈:2019-02-07
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; }