zoukankan      html  css  js  c++  java
  • C#应用视频教程2.4 OPENGL虚拟仿真介绍

    这一部分我们首先实现视图控制(包括了平移/旋转/缩放),前面我们已经讲过,通过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

     

     

  • 相关阅读:
    HLG 1522 子序列的和【队列的应用】
    POJ 3273 Monthly Expense【二分】
    HDU 4004 The Frog's Games 【二分】
    POJ 2001 Shortest Prefixes【第一棵字典树】
    POJ 2823 Sliding Window【单调对列经典题目】
    HDU 1969 Pie 【二分】
    POJ 3125 Printer Queue【暴力模拟】
    POJ 3250 Bad Hair Day【单调栈】
    字典树【模板】
    验证码 Code
  • 原文地址:https://www.cnblogs.com/acetaohai123/p/7586764.html
Copyright © 2011-2022 走看看