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


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

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

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

    1. ///
    2. #include
    3. #include
    4. #include
    5. #include
    6. ///
    7. void init(void) {
    8. glClearColor (0.0, 0.0, 0.0, 0.0);
    9. //glShadeModel (GL_FLAT);
    10. }
    11. ///
    12. void draw_triangle(void) {
    13. glBegin (GL_LINE_LOOP);
    14. glVertex2f(0.0, 25.0);
    15. glVertex2f(25.0, -25.0);
    16. glVertex2f(-25.0, -25.0);
    17. glEnd();
    18. }
    19. ///
    20. void display(void) {
    21. glClear (GL_COLOR_BUFFER_BIT);
    22. glLoadIdentity (); ///!!!!
    23. glColor3f (1.0, 1.0, 1.0);
    24. draw_triangle ();
    25. glEnable (GL_LINE_STIPPLE); ///!!!!打开画线型的开关
    26. glLineStipple (1, 0xF0F0);
    27. glLoadIdentity ();
    28. glTranslatef (-20.0, 0.0, 0.0); ///平移
    29. draw_triangle ();
    30. glLineStipple (1, 0xF00F);
    31. glLoadIdentity ();
    32. glScalef (1.5, 0.5, 1.0); ///缩放
    33. draw_triangle ();
    34. glLineStipple (1, 0x8888);
    35. glLoadIdentity ();
    36. glRotatef (90.0, 0.0, 0.0, 1.0); ///旋转,第一个参数是角度,后面三个是旋转的轴
    37. draw_triangle ();
    38. glDisable (GL_LINE_STIPPLE); //*/
    39. glFlush ();
    40. }
    41. //先不看这个
    42. ///
    43. void reshape (int w, int h) {
    44. glViewport (0, 0, (GLsizei) w, (GLsizei) h);
    45. glMatrixMode (GL_PROJECTION);
    46. glLoadIdentity ();
    47. if (w <= h)
    48. glOrtho (-50.0, 50.0, -50.0*(GLfloat)h/(GLfloat)w,
    49. 50.0*(GLfloat)h/(GLfloat)w, -1.0, 1.0);
    50. else
    51. glOrtho (-50.0*(GLfloat)w/(GLfloat)h,
    52. 50.0*(GLfloat)w/(GLfloat)h, -50.0, 50.0, -1.0, 1.0);
    53. glMatrixMode(GL_MODELVIEW);
    54. }
    55. ///
    56. int main(int argc, char** argv) { //int argc, char** argv) {
    57. glutInit(&argc, argv);
    58. glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    59. glutInitWindowSize(500, 500);
    60. glutInitWindowPosition(100, 100);
    61. glutCreateWindow(""); //argv[0]);
    62. init();
    63. glutDisplayFunc(display);
    64. glutReshapeFunc(reshape);
    65. glutMainLoop();
    66. return 0;
    67. }

    运行结果:

    程序分析:

    知识点:

    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.变换的顺序 以及 新的语句使用

    1. ///
    2. #include
    3. #include
    4. #include
    5. #include
    6. ///
    7. void myMainWinDraw(void);
    8. void myMainWinReshape(int _width, int _height);
    9. ///
    10. int winWidth, winHeight;
    11. int control(0);
    12. ///
    13. int main(int argc,char** argv) {
    14. glutInit(&argc,argv);
    15. glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    16. glutInitWindowSize(400, 400);
    17. glutInitWindowPosition(0, 0);
    18. glutCreateWindow("Hello");
    19. glutDisplayFunc(myMainWinDraw);
    20. glutReshapeFunc(myMainWinReshape);
    21. glutMainLoop();
    22. return 0;
    23. }
    24. //先不看这个(的作用)
    25. ///
    26. void myMainWinReshape(int _width, int _height) {
    27. winWidth = _width;
    28. winHeight = _height;
    29. glViewport(0, 0, _width, _height);
    30. }
    31. ///
    32. void myMainWinDraw() {
    33. glClearColor(0.0, 0.0, 0.0, 0.0);
    34. glClear(GL_COLOR_BUFFER_BIT);
    35. glPushMatrix(); //!!!
    36. glLoadIdentity();
    37. //attention: order is very important !!
    38. glRotatef(90, 0.0f, 0.0f, 1.0f); //<<===new!!
    39. glTranslatef(0.75f, 0.0, 0.0f); //<<===new!!
    40. glutWireTeapot(0.25f);
    41. glPopMatrix(); //!!!
    42. glFlush();
    43. }
    44. ///

    运行结果:

    如果改变R和T的顺序:

     运行结果:

    示意图:

    知识点:

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

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

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

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

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

    3.设置相机的位置

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

    1. ///
    2. ///
    3. #include
    4. #include
    5. #include
    6. #define STEP 0.01f
    7. ///
    8. double eyex, eyez, upx;
    9. ///
    10. void myDrawing(void);
    11. void myKeyboard(unsigned char _key, int _x, int _y);
    12. void reshape(GLsizei _wid, GLsizei _hei);
    13. ///
    14. int main(int argc,char** argv) {
    15. glutInit(&argc,argv);
    16. eyex = eyez = 0;
    17. upx = 0;
    18. glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    19. glutInitWindowSize(300, 300);
    20. glutInitWindowPosition(400, 0);
    21. glutCreateWindow("Hello");
    22. glutDisplayFunc(myDrawing);
    23. glutKeyboardFunc(myKeyboard);
    24. glutReshapeFunc(reshape);
    25. glutMainLoop();
    26. return 0;
    27. }
    28. ///
    29. void reshape(GLsizei _wid, GLsizei _hei) {
    30. glViewport(0, 0, _wid, _hei);
    31. glMatrixMode(GL_PROJECTION);
    32. glLoadIdentity();
    33. #if 1
    34. if (_wid<=_hei) {
    35. glOrtho(-3.0, 3.0, -3.0*_hei/_wid, 3.0*_hei/_wid, -3.0, 13.0);
    36. } else {
    37. glOrtho(-3.0*_wid/_hei, 3.0*_wid/_hei, -3.0, 3.0, -3.0, 13.0);
    38. }
    39. #else
    40. gluPerspective(90.0, 1.0, 0, 10.0);
    41. #endif
    42. glMatrixMode(GL_MODELVIEW);
    43. }
    44. ///
    45. // 图形绘制函数
    46. void myDrawing(void) {
    47. glClearColor(0.0, 0.0, 1.0f, 0.0); //设置背景清除蓝色
    48. glClear(GL_COLOR_BUFFER_BIT); //执行清除
    49. glPushMatrix();
    50. glLoadIdentity();
    51. gluLookAt(eyex, 0, eyez, 0, 0, -1, upx, 1, 0); //会在modelview矩阵上叠加
    52. glTranslatef(0.0f, 0.0f, -3.0f);
    53. glutWireTeapot(0.5f);
    54. //gluLookAt(eyex, 0, eyez, 0, 0, -1, upx, 1, 0); //会在modelview矩阵上叠加----顺序
    55. glPopMatrix();
    56. glFlush();
    57. }
    58. ///
    59. // 键盘事件处理函数 <==========NEW!!!
    60. void myKeyboard(unsigned char _key, int _x, int _y) {
    61. switch (_key) {
    62. case 'w': eyex += STEP; break;
    63. case 's': eyex -= STEP; break;
    64. case 'r': eyez += STEP; break;
    65. case 'f': eyez -= STEP; break;
    66. case 'e': upx += STEP; break;
    67. case 'd': upx -= STEP; break;
    68. }
    69. glutPostRedisplay();
    70. }

     知识点:

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

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

    相机的位置向x轴正半轴(右)移动,按照我的直觉来看,物体在屏幕上应该向左移动。但事实时,当我按下“w”键时,物体在屏幕上却是向右移动的。和我的直觉出现了相反的走向,然后拉来了我的同门来一起思考,也确实获得了启发。伟大的OGL这么多年了,不会出错,出错的是我们自己的认知和思维。我想错了,也想简单了。想简单是因为想错了。

    中间三个参数,指向的是一个具体的点,而不是一个方向,相机位置在移动的过程中,也始终指向这个点。

    物体的位置被平移到了(0,0,-3)。上面那个图 相机指向的观察点是(0,0,-1),下面那个图 相机指向的是(0,0,-4),这两种情况体现的相机在x轴上左右移动对应的物体在屏幕上移动的走向相反。其实,-3是那个分界点。如果相机指向的观察点是(0,0,-3),那么相机是始终对准物体的。

    空间感,烧脑子。

  • 相关阅读:
    PHP框架详解 - Laravel 框架
    能率携手梦想改造家,打造适老化住宅新典范
    股票预测和股票分析就用FineBI!
    线性回归模型进行特征重要性分析
    IT行业哪个方向比较好就业?
    蓝牙启动流程梳理
    LVGL V8.3 使用lvgl文件系统读取SD卡内容基于Arduino
    SpingMyc项目如何搭建
    【数组拷贝+二维数组遍历】
    AVR128单片机 自动售水机
  • 原文地址:https://blog.csdn.net/zzz_zzzz_/article/details/134481516