OpenGL 的学习之路-4(变换)

三大变换:平移、缩放、旋转(通过这三种变换,可以将图像移动到任意位置)

其实,这背后对应的数学在 闫令琪 图形学课程 中有过一些了解,所以,理解起来也不觉得很困难。看程序吧。

1.画三角形(运用三种变化效果)

cpp 复制代码
///
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <stdlib.h>


///
void init(void) {
   glClearColor (0.0, 0.0, 0.0, 0.0);
   //glShadeModel (GL_FLAT);
}


///
void draw_triangle(void) {
   glBegin (GL_LINE_LOOP);
   glVertex2f(0.0, 25.0);
   glVertex2f(25.0, -25.0);
   glVertex2f(-25.0, -25.0);
   glEnd();
}


///
void display(void) {
   glClear (GL_COLOR_BUFFER_BIT);

   glLoadIdentity (); ///!!!!
   glColor3f (1.0, 1.0, 1.0);
   draw_triangle ();

   glEnable (GL_LINE_STIPPLE); ///!!!!打开画线型的开关

   glLineStipple (1, 0xF0F0);
   glLoadIdentity ();
   glTranslatef (-20.0, 0.0, 0.0);  ///平移
   draw_triangle ();

   glLineStipple (1, 0xF00F);
   glLoadIdentity ();
   glScalef (1.5, 0.5, 1.0);   ///缩放
   draw_triangle ();

   glLineStipple (1, 0x8888);
   glLoadIdentity ();
   glRotatef (90.0, 0.0, 0.0, 1.0);   ///旋转,第一个参数是角度,后面三个是旋转的轴
   draw_triangle ();

   glDisable (GL_LINE_STIPPLE); //*/

   glFlush ();
}

//先不看这个
///
void reshape (int w, int h) {
   glViewport (0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();
   if (w <= h)
      glOrtho (-50.0, 50.0, -50.0*(GLfloat)h/(GLfloat)w,
         50.0*(GLfloat)h/(GLfloat)w, -1.0, 1.0);
   else
      glOrtho (-50.0*(GLfloat)w/(GLfloat)h,
         50.0*(GLfloat)w/(GLfloat)h, -50.0, 50.0, -1.0, 1.0);
   glMatrixMode(GL_MODELVIEW);
}



///
int main(int argc, char** argv) { //int argc, char** argv) {
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
   glutInitWindowSize(500, 500);
   glutInitWindowPosition(100, 100);
   glutCreateWindow(""); //argv[0]);

   init();

   glutDisplayFunc(display);
   glutReshapeFunc(reshape);

   glutMainLoop();

   return 0;
}

运行结果:

程序分析:

知识点:

1.**glLoadIdentity ()**所有的变换操作是放在一个栈中的,在施加一个新变化上,该语句的作用是向栈中压入一个I(单位阵),也就是现在还无变换。方便后续操作。

2.**glTranslatef (-20.0, 0.0, 0.0)**平移操作,向x轴的负半轴平移20个单位。该语句施加在前面I之上,相当于该平移变换起作用。

3.glScalef (1.5, 0.5, 1.0) 缩放操作,x轴坐标变为原来的1.5倍,y轴坐标变为原来的0.5倍。该语句施加在前面I之上,相当于该缩放变换起作用。

4.glRotatef (90.0, 0.0, 0.0, 1.0) 旋转操作,以(0,0,1)也就是z轴为旋转轴,旋转度数为90度。该语句施加在前面I之上,相当于该旋转变换起作用。

2.变换的顺序 以及 新的语句使用

cpp 复制代码
///
#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>
#include <iostream>


///
void myMainWinDraw(void);
void myMainWinReshape(int _width, int _height);


///
int winWidth, winHeight;
int control(0);


///
int main(int argc,char** argv) {
    glutInit(&argc,argv);
	glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
	glutInitWindowSize(400, 400);
	glutInitWindowPosition(0, 0);

	glutCreateWindow("Hello");

	glutDisplayFunc(myMainWinDraw);
	glutReshapeFunc(myMainWinReshape);

	glutMainLoop();

   return 0;
}

//先不看这个(的作用)
///
void myMainWinReshape(int _width, int _height) {
	winWidth  = _width;
	winHeight = _height;
	glViewport(0, 0, _width, _height);
}


///
void myMainWinDraw() {
	glClearColor(0.0, 0.0, 0.0, 0.0);
	glClear(GL_COLOR_BUFFER_BIT);

	glPushMatrix();  //!!!

	glLoadIdentity();
    //attention: order is very important !!
    glRotatef(90, 0.0f, 0.0f, 1.0f); //<<===new!!
    glTranslatef(0.75f, 0.0, 0.0f);   //<<===new!!
    glutWireTeapot(0.25f);

    glPopMatrix();   //!!!

	glFlush();
}

///

运行结果:

如果改变R和T的顺序:

运行结果:

示意图:

知识点:

1.**glPushMatrix()**将存着变换的栈中的栈顶矩阵复制一份再放到栈顶。

2.**glLoadIdentity ()**将那个栈顶的矩阵变换为单位阵 I。

3.如果有多个变换的函数,先施行的是最下面的,然后往上进行。

4.glPopMatrix() 将栈顶的矩阵弹出,这样比较安全。变换前后,保持了栈中的状态没有变化。

(以上三种变换属于模型变换)

3.设置相机的位置

拍摄受相机的影响,影响相机的三个因素:相机的位置、相机的指向、相机的top方向。如果把相机比作人的眼睛的话,眼睛的位置、眼睛看向哪里、头的歪头。

cpp 复制代码
///
///

#include <GL/gl.h>
#include <GL/glu.h>
#include <GL/glut.h>

#define STEP  0.01f


///
double eyex, eyez, upx;

///
void myDrawing(void);
void myKeyboard(unsigned char _key, int _x, int _y);
void reshape(GLsizei _wid, GLsizei _hei);


///
int main(int argc,char** argv) {
    glutInit(&argc,argv);
	eyex = eyez = 0;
	upx  = 0;

	glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
	glutInitWindowSize(300, 300);
	glutInitWindowPosition(400, 0);
	glutCreateWindow("Hello");

	glutDisplayFunc(myDrawing);
	glutKeyboardFunc(myKeyboard);
	glutReshapeFunc(reshape);

	glutMainLoop();

   return 0;
}


///
void reshape(GLsizei _wid, GLsizei _hei) {
	glViewport(0, 0, _wid, _hei);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

#if 1
	if (_wid<=_hei) {
		glOrtho(-3.0, 3.0, -3.0*_hei/_wid, 3.0*_hei/_wid, -3.0, 13.0);
	} else {
		glOrtho(-3.0*_wid/_hei, 3.0*_wid/_hei, -3.0, 3.0, -3.0, 13.0);
	}
#else
	gluPerspective(90.0, 1.0, 0, 10.0);
#endif

	glMatrixMode(GL_MODELVIEW);
}

///
// 图形绘制函数
void myDrawing(void) {
	glClearColor(0.0, 0.0, 1.0f, 0.0);  //设置背景清除蓝色
	glClear(GL_COLOR_BUFFER_BIT);       //执行清除

	glPushMatrix();
	  glLoadIdentity();
	  gluLookAt(eyex, 0, eyez, 0, 0, -1, upx, 1, 0);  //会在modelview矩阵上叠加
	  glTranslatef(0.0f, 0.0f, -3.0f);
	  glutWireTeapot(0.5f);
	  //gluLookAt(eyex, 0, eyez, 0, 0, -1, upx, 1, 0);  //会在modelview矩阵上叠加----顺序
	glPopMatrix();

	glFlush();
}



///
// 键盘事件处理函数               <==========NEW!!!
void myKeyboard(unsigned char _key, int _x, int _y) {
	switch (_key) {
	case 'w': eyex += STEP; break;
	case 's': eyex -= STEP; break;

	case 'r': eyez += STEP; break;
	case 'f': eyez -= STEP; break;

	case 'e': upx += STEP; break;
	case 'd': upx -= STEP; break;
	}

	glutPostRedisplay();
}

知识点:

1.**gluLookAtt(eyex, 0, eyez, 0, 0, -1, upx, 1, 0)**9个参数,三个一组,前三个是相机的位置,中间三个是相机看向的方向,后三个是相机的top方向。这里,一开始,相机位于原点位置,相机看向z轴负半轴(也就是屏幕里),相机的top方向是y轴的正方向。

2.这里使用了键盘事件处理的回调函数 来实现 漫游(相机的移动)。

相关推荐
Luis Li 的猫猫2 小时前
深度学习中的知识蒸馏
人工智能·经验分享·深度学习·学习·算法
鹿鸣悠悠4 小时前
第二月:学习 NumPy、Pandas 和 Matplotlib 是数据分析和科学计算的基础
学习·numpy·pandas
Java能学吗5 小时前
2.17学习总结
数据结构·学习
靡不有初1116 小时前
CCF-CSP第31次认证第二题——坐标变换(其二)【NA!前缀和思想的细节,输出为0的常见原因】
c++·学习·ccfcsp
虾球xz9 小时前
游戏引擎学习第108天
学习·游戏引擎
初尘屿风10 小时前
小程序类毕业设计选题题目推荐 (29)
spring boot·后端·学习·微信·小程序·课程设计
虾球xz10 小时前
游戏引擎学习第112天
java·学习·游戏引擎
小呀小萝卜儿11 小时前
2025-02-18 学习记录--C/C++-PTA 7-24 约分最简分式
c语言·学习
S火星人S11 小时前
FATFS学习(2.2):ffconf.h
学习
啥也不会的菜鸟·12 小时前
Redis7——基础篇(三)
redis·学习·缓存