位置: 编程技术 - 正文

[OpenGL ES 04]3D变换实践篇:平移,旋转,缩放

编辑:rootadmin

推荐整理分享[OpenGL ES 04]3D变换实践篇:平移,旋转,缩放,希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:,内容如对您有帮助,希望把文章链接给更多的朋友!

[OpenGL ES ]3D变换实践篇:平移,旋转,缩放

罗朝辉 ( ES ]3D变换:模型,视图,投影与Viewport》中已经详细介绍了3D变换相关的数学知识,也讲了基本的模型变换:平移,旋转与缩放,如果你还没有阅读前文或对这些知识还不够明白,务必先弄懂前文再继续。假如你已经准备好继续了,那么在接下来的内容中,我将介绍如何在 OpenGL ES 中运用这些知识,来渲染一个四棱锥,并对它进行平移,旋转与缩放操作,此外本文也演示了如何将 OpenGL View 与 UIView 结合在一起(注意:在实际运用中,不推荐这么做,混合使用 OpenGL View 和 UIView 对效率影响较大)。

本文代码可以从这里获得:点此下载(Tutorial),最终效果图如下:

一,创建工程

1,新建工程

从今天起,我们不再从头开始创建 window 和 view 了,新建一个名为 Tutorial 的 Single view application 工程:

2,从前面的效果图中可以看到,在这个教程中,我们需要两个 view:OpenGL view 和 UIView。因此打开 MainStoryboard.storyboard,向其中加入两个 view,其中上面那一个用于 OpenGL view,下面那一个用于 control view。调整两个view 的大小与位置,将下面的 view 的背景设置为浅蓝色,以方便区分。

3,拷贝 Tutorial 教程中的 GLESUtils.h, GLESUtils.m OpenGLView.h, OpenGLView.m 以及 FragmentShader.glsl, VertexShader.glsl 到 Tutorial 中,并加入到工程中进来,再添加 OpenGLES 以及 QuartzCore framework。

4,在 ViewController.h 中,为这两个view 添加 IBOutlet:

在 ViewController.m 中 @implementation ViewController 下面的添加

并在 viewDidUnload 中进行清理:

5,回到 MainStoryboard.storyboard,将上面那个 view 的类型设置为 OpenGLView,并关联相关的 IBOutlet:

二,描绘四棱锥

1,在 Tutorial 中只描绘了一个三角形,这回我们来描绘一个真正的 3D 物体:四棱锥。在 OpenGLView.m 中 render() 上面添加如下函数:

这次我们使用顶点索引数组结合 glDrawElements 来渲染,而在 Tutorial 中,使用的是 glDrawArrays。使用顶点索引数组有什么好处呢?很明显,我们可以减少存储重复顶点的内存消耗。比如在本例的索引表中,我们重复利用了顶点 0,1,2,3,4,它们对应 vertices 数组中5个顶点(三个浮点数组成一个顶点)。

glDrawElements 函数的原型为:

第一个参数 mode 为描绘图元的模式,其有效&#;为:GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN。这些模式具体含义下面有介绍。

第二个参数 count 为顶点索引的个数也就是,type 是指顶点索引的数据类型,因为索引始终是正&#;,索引这里必须是无符号型的非浮点类型,因此只能是 GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT 之一,为了减少内存的消耗,尽量使用最小规&#;的类型如 GL_UNSIGNED_BYTE。

第三个参数 indices 是存放顶点索引的数组。(indices 是 index 的复数形式,3D 里面很多单词的复数都挺特别的。)

2,使用

修改 render() 函数如下:

编译运行程序,你就应该就能看到一个四棱锥了。

也许你会说,怎么看起来不像呢?那是因为你是从四棱锥的正上方朝下俯视它,索引四棱锥的尖顶(就是图中间交叉的那个点)看起来就是平的了。如果我们给程序加入旋转功能,那就会看得非常明显了,在介绍完图元模式之后,我们将加入旋转功能。

三,图元模式介绍:

对于画 line 来说有三种模式:

此外还可以通过函数 glLineWidth(GLfloat width) 来设定线的宽度,要获得当前设置的线宽度可以使用如下代码:

在 Tutorial 教程中,我们使用模式 GL_TRIANGLES 描绘了一个三角形。对于三角形来说也有三种模式:

OpenGL ES 还支持描绘点(精灵, sprite)的模式:GL_POINTS,此外还可以通过内建变量 gl_PointSize 来设置点精灵的大小,要获取当前设置的点精灵的大小可以使用如下代码:

四,平移

1,添加控件

为了加入平移控制,我们需要在下面的 view 上面添加滑块对平移的距离进行调节。为此,打开 MainStoryboard.storyboard,在下面浅蓝色背景的 UIView 上添加一个 UILabel 和 UISlider。

并设置滑块的最大&#; 3,最小&#; -3 和当前&#; 0 :

2,加入控件关联代码

在 ViewController.h 中加入滑块的 IBOutlet 和 IBAction,并将它与 UISlider 关联起来。

在 ViewController.m 中加入:

这时,如果你拖动滑块,就能输出滑块当前的&#;。不要忘记在 viewDidUnload 清理该滑块:

3,加入平移代码

[OpenGL ES 04]3D变换实践篇:平移,旋转,缩放

为了让我们的三棱锥可以在 x 轴上移动,打开 OpenGLView.h,在 @interface 中加入:

然后再加入属性:

打开 OpenGLView.m,加入:

4,修改顶点着色器代码

打开 VertexShader.glsl,修改其内容如下:

在上面的代码中,我们对输入顶点进行了自定义的投影和模型视图变换,还记得在前文中介绍的内容么?尤其是左乘,在这里,顶点先进行模型视图变换,然后再进行投影变换。

5,增加实现 Transform 代码

回到 OpenGLView.h 中,加入对应的投影矩阵与模型视图矩阵:

KSMatrix4 是定义在数学辅助库 GLESMath 中用 4 * 4 的二维数组表示的矩阵,你可以在这里获取 GLESMath.h 和 GLESMath.c,并将它们加入工程中。这个数学辅助库中包含了常见的一些 3D 计算,后面还会提到它。

在 OpenGLView.m 中,在 setupProgram 的最后加入获取模型视图矩阵以及投影矩阵变量的槽位:

在OpenGLView 的匿名 category 中加入以下两个函数声明:

然后在 @implemetion 中实现它们:

上面的代码中,ksMatrixLoadIdentity 是 GLESMath 中的一个数学函数,用来将指定矩阵重置为单位矩阵,而 ksPerspective 与前文中讲到的 gluPersoective 作用一样。在这里,我们设置视锥体的近裁剪面到观察者的距离为 1, 远裁剪面到观察者的距离为 ,视角为 度,然后装载投影矩阵。默认的观察者位置在原点,视线朝向 -Z 方向,因此近裁剪面其实就在 z = -1 这地方,远裁剪面在 z = - 这地方,z &#;不在(-1, -) 之间的物体是看不到的。不要忘记在初始化代码中调用该函数:

下面的代码是更新模型视图矩阵,以响应用户的控制。

上面的代码中,ksTranslate,ksRotate,ksScale 也是 GLESMath 中的数学函数,作用与 glTranslate,glRotate,glScale 相同,分别用于平移,绕轴旋绕以及缩放。在这里,设置在 x 方向上平移,平移量将由 self.posX 控制,而这个属性最终是由滑块控制的,从而达到用户移动物体的目的;将 z 设置为 -5.5 (介于 (-1, -) 之间,前面有讲);此外还设置绕 x 轴旋绕 0 度,在 x,y,z三个方向上缩放 1 倍,这两个函数的调用是为下一步的旋转和缩放控制准备的。最后,装载模型视图矩阵。

由于需要在 posX 的&#;变化时,及时更新模型视图矩阵,并重新描绘,以便能及时看到效果,我们得自己实现属性 posX 的 setter 和 getter 方法:

6,至此,下层的控制代码就绪了,我们来实现上层 UI 的响应代码,修改 ViewController.m 中的 xSliderValueChanged 方法如下:

7,编译运行,滑动滑块你就能够控制四棱锥在 x 方向上来回移动了(还记得前面限制了 x 的位置只能在 (-3, 3) 之间么,这是为了不让四棱锥跑到屏幕外边去)。聪明的你,应该很容易实现如何控制在 y 和 z 方向的移动了。在实现的过程中要注意,y 滑块的取&#;范围也为(-3, 3),默认&#;为0,而 z 滑块的取&#;范围为(-, -1),默认&#;居中为-5.5。这样的设置可以确保物体不会完全跑出视锥体所圈定的范围,因为视锥体之外的物体是不可见的。比如下图中四棱锥的尖顶部分就跑到视锥体的近裁剪面外面去了,所以尖顶就被裁剪了。

五,旋绕,缩放

1,实现下层控制代码

有了控制平移的基础,我们也很容易就能控制旋转与缩放。我们还是从下层开始,修改 OpenGLView.h 中的代码(我将在 y 和 z 方向平移的代码放在这里了,希望你是自己实现它的):

修改 OpenGLView.m 中的代码:

前面说过,我们需要自己实现这些属性的 setter 和 getter 方法,在这里就不一一列出了, 它们与 setPosX 和 posX 的实现是类&#;的。我们需要让这些属性来控制模型视图矩阵,因此还要更新 updateTransform 方法如下:

这样四棱锥就能绕 x 轴旋转 rotateX 角度,并在 z 方向上缩放 scaleZ 倍。注意:属性 scaleZ 默认&#;为 0,所以我们需要对它进行初始化,此外为了能方便重置模型视图矩阵,我实现了 resetTransform,该方法在 initWithCoder 方法的最后被调用。

2,添加上层控制代码

打开 MainStoryboard.storyboard,在下方的 control view 中添加滑块与按钮,如图所示:

然后修改 ViewController.h 为:

在 ViewController.m 中添加属性相关代码:

以及响应事件的方法:

上面的代码很简单,基本与平移 x 的代码类&#;,所以在这里也就不一一讲述了。然后回到 MainStoryboard.storyboard 中,使用拖拽技巧将相关属性和事件与控件关联起来。

3,编译运行,滑动不同的滑块,体验下 3D 变换的效果。

六,自动旋转与重置

1,重置恢复默认状态

还记得在前面我提到有一个重置模型视图矩阵的方法么,如果想让物体恢复默认状态,只要调用此方法,再重新描绘即可。因此,resetButtonClick 实现如下:

在 Tutorial 教程中 render 方法是私有方法,在这里,需要把它修改为公开方法。resetControls 是用来设置控件的默认&#;,以保持模型矩阵与控件的相关&#;同步,记得在 viewDidLoad 中调用此函数。编译运行,无论你做了多么复杂的变换,只要按下 Reset 按钮,一切都恢复原样了。

2,自动旋转

下面来添加点好玩的,让物体自动绕 X 轴旋转。这通常是通过 timer 来实现的,但苹果为我们提供了更好的办法:CADisplayLink(其实它内部也是使用的 timer),它可以让我们的应用程序与屏幕的刷新率保持同步,每当屏幕刷新时,就会调用我们提供的回调函数。下面我们来使用它,在 OpenGLView.m 中的匿名 category 中添加成员变量:

并添加回调函数声明:

然后在下面的 @implemetion 中实现此回调,屏幕没刷新一次就让四棱锥绕 x 轴旋转一定的角度:

在 OpenGLView.h 中添加公开方法:

然后在 OpenGLView.m 中实现之:

在上面的代码中,我们实现了一个 toggle 开关方法,如果没有自动旋转,那么就启动自动旋转;如果已经在自动旋转了,那么就停止它。CADisplayLink 的使用很简单,创建一个对象,设置它的 target 和回调函数,然后将它加入 NSRunLoop 中开始运行;如果要停止它,首先调用 invalidate 方法,然后将它从 NSRunLoop 中移除。

最后,我们在按钮的响应方法中添加对 toggleDisplayLink 的调用:

编译运行代码,点击 Auto 就能让四棱锥自动旋转了,再次点击就能让它停止自动旋转,很妙吧?

七,总结

在这一篇文章中,介绍了如何通过 3D 变换来实现平移,旋转和缩放,以更好地理解前文中介绍的理论知识;同时也实现了如何通过 UIControl 来控制 OpenGL View 中的物体;此外还详细介绍了描绘图元的模式以及顶点索引模式。在文章的最后,介绍了如何使用 CADisplayLink 来实现动画效果。

最后,四棱锥看起来有点丑陋,来个水立方怎么样?(长方体),这个任务就交给看官你了,相信你一定可以实现的。

&#;GL_COMBINE_ARB&#; : undeclared &#;GL_RGB_SCALE_ARB&#; : undeclared 问题 如果你在弄GL的过程中遇见了这个问题,那么你可以在对应的头文件里进行如下的宏定义就OK了。修改:#defineGL_TEXTURE0_ARB0xC0#defineGL_TEXTURE1_ARB0xC1#defineG

opengl的初始化(VS MFC) 吐血写贴,试了整整一天有木有。。。。。。桑心有木有。。。。。好了不废话了,先把流程整理一下,然后有时间再解释代码~~~第一步:新建MFC项目

OpenGL教程翻译 第十四课 相机控制(一) OpenGL教程翻译第十四课相机控制(一)原文地址:

标签: [OpenGL ES 04]3D变换实践篇:平移,旋转,缩放

本文链接地址:https://www.jiuchutong.com/biancheng/369515.html 转载请保留说明!

上一篇:mac xcode运行opengl(mac vscode opengl)

下一篇:'GL_COMBINE_ARB' : undeclared 'GL_RGB_SCALE_ARB' : undeclared 问题

  • 企业注销库存怎么做账务处理
  • 一般纳税人购入固定资产的账务处理
  • 公益募捐什么意思
  • 抄报税校验失败调用系统服务出错怎么办
  • 民间非营利组织会计制度最新版
  • 生产事故造成怎么样赔付
  • 开立基本账户所需资料
  • 客户能把货款打给个人吗
  • 资金账号和交易账号一样吗
  • 多计提以前年度损益调整账务处理怎么做
  • 企业预收款项业务不多的情况下可以不设置预收账款科目
  • 城镇土地使用税征收标准及计算方法
  • 怎么确定是不是本人
  • 公司获得奖金计入什么科目
  • 购进建筑服务进项税额
  • 普通增值税发票查询结果不一致是什么原因?
  • 取得稳岗补贴后怎么办
  • 同一控制下的企业合并的会计核算方法
  • 外购库存商品
  • 直接快递到国外的货物如何收汇?
  • 公司租赁办公场地用缴纳房产税吗
  • 商业现金折扣计算
  • 收购报废车有利润吗
  • 所得税申报怎么弥补以前年度亏损
  • 企业为员工缴纳社保可以抵税吗
  • 英雄联盟登录失效怎么回事
  • 企业所得税是什么时候计提
  • 周转材料计划成本会计分录
  • 销售设备并提供安装服务增值税税率
  • 提供给生产工人的住房的租赁费用应计入
  • 承兑找零怎么做凭证
  • 对公账户开户费开户的时候就要交钱吗
  • php多维数组合并相同key
  • 其他应收款的会计处理
  • 提高stable diffusion速度
  • php strftime
  • 旅游业纳税筹划方案
  • 年报中投资总额怎么填
  • 税控盘的发票怎么做账
  • 资产减值损失和存货跌价准备有什么区别
  • 计算md5值命令
  • 什么是半监督算法
  • 小规模纳税人的企业所得税怎么算
  • 文化事业建设费征收范围及计税依据
  • 职工教育经费申报表如何填写
  • 公司一般户财务负责人是另一公司法人
  • 百旺金赋怎么开红字发票
  • 企业残保金什么情况下可以减免
  • 自制半成品属于什么会计要素
  • 机票报销是什么发票
  • 过路费发票抵扣政策
  • 应交税费科目怎么调整
  • 软件企业技术开发增值税税率
  • 企业工会经费计提比例
  • 本期已认证且不抵扣怎么申报
  • 暂估入账是什么意思
  • 外经证适用范围
  • 房地产企业发行长期债券的增信方式有哪些
  • mysql 索引的类型
  • mysql怎么修改用户名和密码
  • Windows 10 与 MySQL 5.5 安装使用及免安装使用详细教程(图文)
  • Win2008 Server Core如何操作?5个步骤学会Win2008 Server Core操作
  • win7 64位运行软件提示MSCOMCTL.OCX丢失或无效该怎么办?
  • windows server 2003 sp3
  • 苹果mac 最新系统
  • windows任务管理器怎么用
  • 如何修复hosts文件
  • win10开机显示recover
  • cocos2dx视频教程
  • 安卓listview用法
  • 基于jquery实现小说
  • unity连接数据库能做什么
  • Android UI之GridLayout(网格布局)
  • 一个页面
  • 河南洛阳医疗保险电话
  • 山东省国家税务局官网
  • 宁波银行税务贷简介
  • 新的国家税务局发票怎么冲红
  • 个人领税票需要哪些资料
  • 北京市印花税减免政策
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设