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

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

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

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

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

///
#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方向。如果把相机比作人的眼睛的话,眼睛的位置、眼睛看向哪里、头的歪头。

///
///

#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.这里使用了键盘事件处理的回调函数 来实现 漫游(相机的移动)。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/162261.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

量化交易:公司基本面的量化

公司的基本面因素一直具备滞后性&#xff0c;令基本面的量化出现巨大困难。而从上市公司的基本面因素来看&#xff0c;一般只有每个季度的公布期才会有财务指标的更新&#xff0c;而这种财务指标的滞后性对股票表现是否有影响呢&#xff1f;如何去规避基本面滞后产生的风险呢&a…

网站SEO优化

网站SEO优化 浏览722 一、合理的title、description、keywords 搜索对着三项的权重逐个减小&#xff0c;title值强调重点即可&#xff1b;description把页面内容高度概括&#xff0c;不可过分堆砌关键词&#xff1b;keywords列举出重要关键词。 1、title title&#xff0c;…

【教3妹学编程-java基础6】详解父子类变量、代码块、构造函数执行顺序

-----------------第二天------------------------ 本文先论述父子类变量、代码块、构造函数执行顺序的结论&#xff0c; 然后通过举例论证&#xff0c;接着再扩展&#xff0c;彻底搞懂静态代码块、动态代码块、构造函数、父子类、类加载机制等知识体系。 温故而知新&#xff…

ZYNQ_project:LCD

模块框图&#xff1a; 时序图&#xff1a; 代码&#xff1a; /* // 24h000000 4324 9Mhz 480*272 // 24h800000 7084 33Mhz 800*480 // 24h008080 7016 50Mhz 1024*600 // 24h000080 4384 33Mhz 800*480 // 24h800080 1018 70Mhz 1280*800 */ module rd_id(i…

【MySQL】InnoDB和MyISAM区别详解(MySQL专栏启动)

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;2022年度博客之星全国TOP3&#xff0c;专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化&#xff0c;文章内容兼具广度、深度、大厂技术方案&#xff0c;对待技术喜欢推理加验证&#xff0c;就职于…

OpenCV C++ 图像 批处理 (批量调整尺寸、批量重命名)

文章目录 图像 批处理(调整尺寸、重命名)图像 批处理(调整尺寸、重命名) 拿着棋盘格,对着相机变换不同的方角度,采集十张以上(以10~20张为宜);或者棋盘格放到桌上,拿着相机从不同角度一通拍摄。 以棋盘格,第一个内焦点为坐标原点,便于计算世界坐标系下三维坐标; …

【代码随想录】算法训练计划24

回溯模板&#xff1a; 1、77. 组合 题目&#xff1a; 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 思路&#xff1a; 很经典的回溯&#xff0c;也是回溯中模板的经典应用&#xff0c;因而是回溯中的简单题…

97.qt qml-自定义Table之实现ctrl与shift多选

我们之前实现了:93.qt qml-自定义Table优化(新增:水平拖拽/缩放自适应/选择使能/自定义委托)-CSDN博客 实现选择使能的时候,我们只能一行行去点击选中,非常麻烦,所以本章我们实现ctrl多选与shift多选、 所以在Table控件新增两个属性: 1.实现介绍 ctrl多选实现原理:当我…

Redis新操作

1.Bitmaps 1.1概述 Bitmaps可以对位进行操作&#xff0c;实际上它就是一个字符串&#xff0c;可以将Bitmaps想象为一个以位为单位的数组&#xff0c;数组中的每个元素只能存储0或者1&#xff0c;数组的下标在Bitmaps被称为偏移量。 setbit key offset value&#xff1a;设置o…

Filter和ThreadLocal结合存储用户id信息

ThreadLocal并不是一个Thread&#xff0c;而是Thread的局部变量。当使用ThreadLocal维护变量时&#xff0c;ThreadLocal为每个使用该变量的线程提供独立的变量副本&#xff0c;所以每一个线程都可以独立地改变自己的副本&#xff0c;而不会影响其它线程所对应的副本。ThreadLoc…

M2 Mac Xcode编译报错 ‘***.framework/‘ for architecture arm64

In /Users/fly/Project/Pods/YYKit/Vendor/WebP.framework/WebP(anim_decode.o), building for iOS Simulator, but linking in object file built for iOS, file /Users/fly/Project/Pods/YYKit/Vendor/WebP.framework/WebP for architecture arm64 这是我当时编译模拟器时报…

cesium 重点区域大屏展示效果(加载行政区划)

cesium 重点区域大屏展示效果(配色不太好看,主要看思路和方法) 1、实现思路(文张最后有**源码 **) 1、第一步将cesium背景调成透明关掉光照大气等效果相关属性都在“viewer.scene”中 2、第二步添加背景图片此背景图片直接用html加css就可以完成 3、第三步添加蒙版效果也…

汇编基础知识

1.1 机器语言 机器语言就是一些二进制代码&#xff0c;存放在内存中。它是机器指令的集合&#xff0c;所谓机器指令就是机器能够正确执行的命令 1.2 汇编语言的产生 1.汇编语言的主体是汇编指令 2.汇编指令实际上就是机器指令的助记符。它们的唯一区别在于书写方式上 寄存器…

S7-1200PLC 作为MODBUSTCP服务器通信(多客户端访问)

S7-1200PLC作为MODBUSTCP服务器端通信编程应用&#xff0c;详细内容请查看下面文章链接&#xff1a; ModbusTcp通信(S7-1200PLC作为服务器端)-CSDN博客文章浏览阅读239次。S7-200Smart plc作为ModbusTcp服务器端的通信S7-200SMART PLC ModbusTCP通信(ModbusTcp服务器)_s7-200 …

Linux嵌入式I2C协议笔记

硬件: 1.I2C结构 在一个SOC中有一个或者多个I2C控制器,一个I2C控制器可以连接一个或多个I2C设备。 I2C总线需要两条线,时钟线SCL和数据线SDA 2.I2C传输数据格式 开始信号(S):SCL为高电平时,SDA山高电平向低电平跳变,开始传送数据。结束信号(P):SCL为高电平时,SDA…

Python中的实例属性和类属性

在这篇文章中&#xff0c;我们将探讨Python中的类是如何工作的&#xff0c;主要介绍实例和类的属性。这些属性是什么&#xff0c;它们之间的区别&#xff0c;以及创建和利用它们的python方法。 类属性与实例属性 首先&#xff0c;我们需要知道什么是实例。实例是属于类的对象。…

Docker安装Zookeeper

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

数据结构前言(空间复杂度)

1.空间复杂度 空间复杂度也是一个数学表达式&#xff0c;是对一个算法在运行过程中临时占用存储空间大小的量度 。 空间复杂度不是程序占用了多少bytes的空间&#xff0c;因为这个也没太大意义&#xff0c;所以空间复杂度算的是变量的个数。 空间复杂度计算规则基本跟实践复杂…

在Go编程中调用外部命令的几种场景

1.摘要 在很多场合, 使用Go语言需要调用外部命令来完成一些特定的任务, 例如: 使用Go语言调用Linux命令来获取执行的结果,又或者调用第三方程序执行来完成额外的任务。在go的标准库中, 专门提供了os/exec包来对调用外部程序提供支持, 本文将对调用外部命令的几种使用方法进行总…

Canal+Kafka实现MySQL与Redis数据同步(一)

CanalKafka实现MySQL与Redis数据同步&#xff08;一&#xff09; 前言 在很多业务情况下&#xff0c;我们都会在系统中加入redis缓存做查询优化。 如果数据库数据发生更新&#xff0c;这时候就需要在业务代码中写一段同步更新redis的代码。 这种数据同步的代码跟业务代码糅合…