这一部分我们首先实现视图控制(包括了平移/旋转/缩放),前面我们已经讲过,通过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. 【BZOJ 4171】 4171: Rhl的游戏 (高斯消元)

    4171: Rhl的游戏 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 74  Solved: 33[Submit][Status][Discuss] ...

  2. kotlin 类 接口 抽象类 子类类型有限的class 。sealed class

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha 用 private 封装,可以防止别人修改. 就好像 内有高压,危险,不让碰.

  3. [HNOI2012]集合选数 --- 状压DP

    [HNOI2012]集合选数 题目描述 <集合论与图论>这门课程有一道作业题,要求同学们求出\({1,2,3,4,5}\)的所有满足以 下条件的子集:若 x 在该子集中,则 2x 和 3x ...

  4. [CSAcademy]A-Game

    题目大意: 给你一个只含字符'A'和'B'的串,A和B两人轮流对其中的子串染色,要求被染色的子串中不包含已经被染色的子串. 最后,如果一方染的'A'少,那么这一方胜: 如果双方染的'A'和'B'一样多 ...

  5. maven搭建企业级多模块项目

    1.创建一个maven项目 选择pom 完成 2.创建模块 项目右键选择module,创建模块.创建子模块 其余的打包时都为jar 地址:https://github.com/LeviFromCN/m ...

  6. Java实现-每天三道剑指Offre(2-4)

    实现一个单例模式 /** * 面试题2:实现单例模式 * * @author qiuyong 饿汉式 */ public class Singleton01 { private Singleton01 ...

  7. Nginx反向代理 实现Web负载均衡

    实现负载均衡的方式有很多种,DNS.反向代理.LVS负载均衡器(软件实现).F5(负载均衡器,硬件,非常昂贵)这里我们只提到基于DNS,以及反向代理的方式来实现负载均衡Web服务       DNS服 ...

  8. <摘录>CentOS怎么查看某个命令的源代码

    安装yumdownloader工具: # yum install yum-utils 设置源: [base-src] name=CentOS-5.4 - Base src - baseurl=http ...

  9. Python可执行对象——exec、eval、compile

           Python提供的调用可执行对象的内建函数进行说明,涉及exec.eval.compile三个函数.exec语句用来执行存储在代码对象.字符串.文件中的Python语句,eval语句用来 ...

  10. S3C2440上LCD驱动(FrameBuffer)实例开发讲解

    一.开发环境 主  机:VMWare--Fedora 9 开发板:Mini2440--64MB Nand, Kernel:2.6.30.4 编译器:arm-linux-gcc-4.3.2 二.背景知识 ...