这一部分我们首先实现视图控制(包括了平移/旋转/缩放),前面我们已经讲过,通过lookat一个函数,或者通过translate+rotate两个函数,都能实现视图的控制(两个函数的方式比较简单,但是通用性不够,因为这个更像是画布就像去参观卖房子的模型,你可以把模型随便上下左右移动翻转看外面,但是如果要像第一人称视角到房子里面爬窗户,上房顶,钻地道,这种视角肯定是不够的。可以想象CS游戏中,整个地图场景必然是唯一的,每个游戏玩家都可以控制一组视角,视角的lookat九个参数不同导致了可以仰望,俯瞰,左右扫等等,有兴趣的读者可以去仔细研究实现方法)

 

然而能用按钮控制还是不够方便,很多时候我们需要像Solidworks软件这样能够用鼠标键盘控制,我自己设定的一些简单规则:

鼠标可以控制视图前后左右翻转

按住Shift+鼠标可以控制视图前后左右平移

鼠标滚轮可以控制视图缩放

按住Ctrl,鼠标滚轮可以控制视图绕Z旋转

 

根据这些规则,我们需要在控件初始化的时候添加一组事件绑定(注意要用C#自动补全的方式做,不然后面的参数你不知道怎么写的,比如绑定到KeyDown事件,响应的是KeyEventArgs e,我们可以采集到键盘的按键,如果你自己写就不知道是什么参数类型了)

 

这些事件的绑定你也可以在主窗口中选中指定的控件,查看他所有的事件,双击进去(但是不符合面向对象的写法,假如我们完善了这个类以后要写一个新的项目,难道你每次拖完了这个OPENGL的控件,然后切换到这里,一个一个把事件双击进去生成,然后再复制粘贴代码?肯定效率很低,比较好的做法是自己定义一个类,然后每次初始化只要把这个OPENGLControl类型传递过去,所有的事件响应就一次完成了)

 

在这么多的事件响应中,我们先来看比较简单的几组,鼠标移入和鼠标移出是判断鼠标是否在控件上的(为了防止在鼠标在窗口的其他地方点击按钮,操作也会影响视图,我们定义只要鼠标离开了控件,则全局变量设置为false,就不再修改视图了)。鼠标按下和鼠标抬起来是为了定义是否采集鼠标当前位置的(也是为了防止误判,假定如果鼠标在控件内部移动,只有左键按下之后的移动操作才会产生影响,不按按钮移动鼠标也不修改视图,当然每次MouseDown的时候都要刷新一下当前的位置=记录之前的位置)

 

鼠标移动的事件是真正产生效果的事件,我们每次鼠标往某个方向运动,如果期望视图跟着发生改变,则实际上只要捕捉鼠标前后位置的差异,然后叠加到Translate或者Rotate的三个参数上即可(注意其实是两个参数,因为我们是在二维的电脑屏幕上模拟三维的效果,鼠标只会有X,Y的数值,所以也只能映射到XY的平移或者绕XY的旋转,所以后面会增加一些额外的规则定义Z的平移-缩放,Z的旋转-旋转视图)

 

讲到缩放视图,最方便的是用鼠标滚轮实现,鼠标滚轮上滚和下滚,e.Delta数值是正的和负的,为了防止太大的时候缩放的太快,所以如果已经ViewChangeTranslate很小,就缩放的再慢一点(也可以做成一个函数,越远越小则缩放越快,这样更符合用户体验)绕Z轴旋转还是比较重要的,为了防止规则太多,我还是用鼠标滚轮实现(需要先按下Ctrl键),到这里基本的视图控制就完成了。

 

然后深入理解一下PushMatrix和PopMatrix方法,假定我们要绘制一个小型的机器人,仅仅用三个六面体来表示机器人的头部和两个手臂(注意尽量绘制一个小模块的时候用一组push和pop包起来),我们后面详细介绍具体绘制过程

 

在绘制基本物体的时候,注意不管你的物体尺寸多少,你的画笔是保持不变的(仅仅Translate和Rotate可以修改画笔的位置和姿态),所以我可以人为地调节红色立方体块的大小

 

接下来绘制手臂,如果期望手臂正好贴在红色立方体块的两个,那么就必须要把画笔平移到下一个要绘制的立方体的底面中心位置(我们暂时还不考虑姿态,后面会讲姿态的文字,如果不使用Rotate,则姿态将始终保持垂直于画布),注意仔细体会画笔挪动到新的位置之后的效果

 

在绘制B手臂的时候,如果直接从绘制A手臂的地方挪过去也可以(再平移整个红色立方体的宽度就行了),但是只是对于简单的几何物体可以这样做,如果绘制非常复杂的多边形,很多时候我们自己也不知道画笔在哪了,所以有必要从上一步画笔还没开始动的地方接着画(因为B手臂跟A手臂是对称的, 所以只要把某些Translate的正负号改一改就行了)下图中从X-X1和X-X2过程基本类似,对称(这也是编程中比较重要的化归思想,不要产生新的问题,X1直接到X2就是新的问题,哪怕比X-X2更简单,因为我们已经有了X-X1的经验可以套用,就可以直接X-X2)

 

让整个动画元素动起来,其实只要把一些变量添加到整个绘制过程就可以了(我在这里只是做了简单的演示,比如两个手臂的摆动,实际上你也可以为机器人添加腿,眼睛,腰部等等)

 

最后套用一点运动控制的思想,让两个旋转的臂从A点走到B点,要求同时走到位(还是要考虑比较多的因素的,比如AB两点没有差距,或者只有一个旋转臂有差距),大体思路可以概括成:

1 采集起点和终点的差值(数组)

2 获取差值数组中的最大值(最远距离)

3 根据给定的速度求总的时间(最远距离/给定速度)

4 根据总的时间重新求每个轴的速度(每个轴的前后距离/总时间)

5 在线程中执行运动(用计时器,每隔一定时间生成一个新的时间,并用S=S0 + V*t的公式计算每次新的位置)

 

总结:到此为止OPENGL的简单介绍就结束了,网上有大量的代码介绍OPENGL的仿真(C++的比较多,因为C#相对于C++的性能还是差很多,所以大型的游戏,3D处理软件都会用C++作为最终的编程执行工具,可能C#是嵌套的上层交互用的),但是并不妨碍我们通过C#加深对OPENGL的理解(核心思想没有变,而且C#的开发,验证效率更高)。读者需要掌握:

1 理解OPENGL的基本绘图过程,平移,旋转,缩放的

2 理解OPENGL绘制基本物体,组合物体的原理,比如小型的摆臂机器人实现原理

3 查看网上的高手的代码,针对某一些具体的功能做深入的研究,OPENGL除了能绘制二维三维的物体,还能做动力学仿真,模型的渲染等,学好这部分内容还是很有意义的

 

 

更多教学视频和资料下载,欢迎关注以下信息:

我的优酷空间:

http://i.youku.com/acetaohai123

 

我的在线论坛:

http://csrobot.gz01.bdysite.com/

 

问题交流:

QQ:910358960

邮箱:acetaohai123@163.com

 

 

C#应用视频教程2.4 OPENGL虚拟仿真介绍的更多相关文章

  1. C#应用视频教程2.1 OPENGL虚拟仿真介绍

    OPENGL的虚拟仿真对于工控自动化的意义很大,虽然市面上有很多的第三方软件比如Solidworks,Mathlab,ProE等等软件可以做仿真,而且能够实现的功能包括了流体分析,力学分析,摩擦力分析 ...

  2. C#应用视频教程2.3 OPENGL虚拟仿真介绍

    本节最重要的一个内容,就是让视野可以平移+旋转+缩放(就像打CS游戏一样以第一人称视角去观察物体,如果可能的话W,S,A,D四个按键控制人物移动,还有鼠标控制视角),本节最重要的一个概念就是设置观察视 ...

  3. C#应用视频教程2.2 OPENGL虚拟仿真介绍

    三维在理解了如何绘制2D元素之后,我们尝试绘制3D元素. 其实多个三角形也能够成四面体,多个长方形也能够成六面体,所以绘制3D元素的时候,只要顶点数量匹配就行了   这里我们尤其注意,我把绘制之前的三 ...

  4. 基于unity3d IFC的虚拟仿真系统

  5. 国家虚拟仿真实验教学项目共享平台(实验空间)PHP SDK

    使用XJWT标准,此标准基于JSON Web Token (JWT)开发.XJWT包含三个参数:header, payload, signature,因此生成token就要先获得这三个参数. clas ...

  6. 2017.04.20 Adams仿真介绍

    Adams 仿真 | 验证"隐性机器人模型"概念,提高视觉伺服精度 产品:Adams行业:科研优势: 1.Adams 仿真可精确预测机器人的位置和方位 2.仿真在理论工作验证中起着 ...

  7. 【转】OpenGL相关函数库介绍

    原文:http://blog.chinaunix.net/uid-20638550-id-1909182.html OpenGL 函数库相关的API有核心库(gl).实用库(glu).辅助库(aux) ...

  8. OpenGL教程(0)——介绍

    OpenGL介绍 OpenGL,全称Open Graphics Library,是一个用C语言写的图形API.通俗地说,OpenGL用来绘制2D/3D图形.目前OpenGL的运用十分广泛,有许多用Op ...

  9. 解析vue2.0的diff算法 虚拟DOM介绍

    react虚拟dom:依据diff算法台 前端:更新状态.更新视图:所以前端页面的性能问题主要是由Dom操作引起的,解放Dom操作复杂性 刻不容缓 因为:Dom渲染慢,而JS解析编译相对非常非常非常快 ...

随机推荐

  1. HDU 6201 transaction transaction transaction(树形DP)

    transaction transaction transaction Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 132768/1 ...

  2. PlayMaker布局技巧:预览GUI界面

    PlayMaker布局技巧:预览GUI界面   PlayMaker提供丰富的动作用来构建界面.对于复杂界面,每次通过调试方式查看效果,会非常麻烦.这个时候,开发者可以考虑使用PlayMaker GUI ...

  3. BZOJ3881 Coci2015 Divljak fail树+差分

    题目大意,给出两个字符串集合S和T,向T中添加字符串,查询S_i在T中有几个字符串出现过.一看这种多字符串匹配问题,我们联想到了AC自动机,做法就是,对于S集合我们建立一个AC自动机,建出fail树, ...

  4. [BZOJ4028][HEOI2015]公约数数列(分块)

    先发掘性质: 1.xor和gcd均满足交换律与结合率. 2.前缀gcd最多只有O(log)个. 但并没有什么数据结构能同时利用这两个性质,结合Q=10000,考虑分块. 对每块记录这几个信息: 1.块 ...

  5. 快速傅里叶变换(FFT)相关内容汇总

    (原稿:https://paste.ubuntu.com/p/yJNsn3xPt8/) 快速傅里叶变换,是求两个多项式卷积的算法,其时间复杂度为$O(n\log n)$,优于普通卷积求法,且根据有关证 ...

  6. 网络流小结+[jzyzoj p1320] patrol

    一个不能更清楚的网络流介绍 ↑虽然不是我写的但是观摩一下总是没问题的嗯   看到晗神学的是神奇的ek算法. 但是看起来还是Ford-Fulkerson比较简单..所以我就学了这个...嗯其他的先看看. ...

  7. Week One

    2018.11.21: 1.[BZOJ 4868][SHOI 2017] 从后往前枚举最后位置即可,如果$A<B$,用尽可能多的$A$替换$B$操作 Tip:很大的$C$可能爆$longlong ...

  8. [BZOJ5028]小Z的加油店

    [BZOJ5028]小Z的加油店 题目大意: 一个长度为\(n(n\le10^5)\)的数列,\(m(m\le10^5)\)次操作,支持区间加和区间\(\gcd\). 思路: 线段树维护差分,\(\g ...

  9. ThinkPHP -- 开发初体验及其几个配置文件的介绍

    ThinkPHP是一款不错的轻量级的PHP+MVC框架,它吸取了Ruby On Rails的特性,不仅将Model.View.Controller分开,而且实现了ORM.模板标签等高级特性.    开 ...

  10. php uncode 转汉字编码

    $test = "%u4E0A%u6D77%u9EC4%u6D66";//$test = '\u5e86\u91cd\u5e86'; //庆重庆$temp = explode('% ...