SharpGL学习笔记(二) 模型变换(几何变换)
(二) 模型变换
模形变换就是指的在世界坐标系中(world space)做“移动”,“旋转", "缩放"三种操作。
首先要说明的,在Opengl中,是用4x4矩阵进行坐标变换,OpenGL的4x4矩阵是按列排列的,就像下面这样。

所谓的模型变换,就是对这个矩阵进行变换。
描述三维世界你就得先设计三维模形。 在设计三维模形的时候,它是们于模形坐标系中的,最终它会放置到世界坐标系统中,如果这个模形设计时处理的好的话,放到世界坐标系中时默认就是模形的中心定位于世界坐标系统的中心处。
这里有一个延伸的知识点:模形放置到世界坐标系时中心不位于世界坐标系中心处,是怎么回事?有什么后果? 这个以后我们会做一个扩展性的讨论。
上面说的是导入其它设计软件制作的模形,比如3dsMax制作的模形的情况。如果我们自己用代码画的模形,自然是默认就位于世界坐标系统的中心。
这个世界坐标系,就像下图一样:
X轴箭头方向为正,反过来为负
Y轴箭头方向为正,反过来为负
Z轴箭头方向正好指向我们的眼睛,因此图上只是个小点,看不见,它负方向向屏幕里面。
而下图中的三维体的中心就刚好们于这个世界坐标系的中心。

下面的演示代码在世界坐标系统中画出一个三角形,再对它做一些变换操作。
using System;
using System.Windows.Forms;
using SharpGL; namespace blankTest
{
public partial class Form1 : Form
{
private int mtype = ;
public Form1()
{
InitializeComponent(); } private void Form1_Load(object sender, EventArgs e)
{ } private void openGLControl1_OpenGLInitialized(object sender, EventArgs e)
{ } private void openGLControl1_Resize(object sender, EventArgs e)
{ } private void openGLControl1_OpenGLDraw(object sender, PaintEventArgs e)
{
SharpGL.OpenGL gl = this.openGLControl1.OpenGL; gl.ClearColor(, , , );
gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT); switch (mtype)
{
case :
translateSample(gl);
break;
case :
rotateSample(gl);
break;
case :
scaleSample(gl);
break;
} gl.Finish();
gl.Flush();
} private void scaleSample(SharpGL.OpenGL gl)
{
gl.LoadIdentity();
gl.Scale(1f, 1f, 1f);
gl.Translate(, , -9f);
drawPT(gl); gl.LoadIdentity();
gl.Scale(5f, 1f, 1f);
gl.Translate(, , -9f);
drawPT(gl);
} private void rotateSample(SharpGL.OpenGL gl)
{
gl.LoadIdentity();
gl.Rotate(,, );
gl.Translate(, , -8f);
drawPT(gl); gl.Rotate(, , );
gl.Translate(-, ,0f);
drawPT(gl);
} private void translateSample(SharpGL.OpenGL gl)
{
gl.LoadIdentity();
gl.Translate(0f, 0f, -3f);
drawPT(gl); gl.LoadIdentity();
gl.Translate(0f, 1f, -3f);
drawPT(gl);
} private void drawPT(SharpGL.OpenGL gl)
{
gl.PointSize(5f);
gl.Begin(OpenGL.GL_TRIANGLES);
{
gl.Vertex(0.0f, 0f, 0.0f);
gl.Vertex(-1.0f, -1f, 0.0f);
gl.Vertex(1.0f, -1f, 0.0f);
}
gl.End();
} private void btnTranslate_Click(object sender, EventArgs e)
{
switch (((Button)sender).Name)
{
case "btnTranslate":
mtype = ;
break;
case "btnRotate":
mtype = ;
break;
case "btnScale":
mtype = ;
break;
}
} }
}
三个函数translateSample(), rotateSample(),scaleSample() 分别演示”平移“,”旋转“,”缩放”。
我们来谈谈一些重点的地方:
在“平移”函数中,如果没有gl.LoadIdentity()函数复位坐标系统到原点位置,那么执行结果会不同,第二条gl.Translate(0f,1f,-3f)将会是相对于上一条gl.Translate的位置(0f,0f,-3f)移动。
而每次绘制三角形之前做一次gl.LoadIdentity(), 相当于每次绘图时的中心点坐标都从原点算起。
private void translateSample(SharpGL.OpenGL gl)
{
gl.LoadIdentity();
gl.Translate(0f, 0f, -3f);
drawPT(gl); gl.LoadIdentity();
gl.Translate(0f, 1f, -3f);
drawPT(gl);
}
gl.Translate中的Z轴设置为0,则物体不可见,因为这时候画出来的三角形,贴着世界坐标系的Z轴。就像你的眼睛贴跟它零距离一般。
你可以想象成摄像机位于世界坐标系统(0,0,0), 走向Z轴的负方向。
为了说明白这点,博主画了个示意图如下:
图中的栅格面就代表了世界坐标系平面,两条相互垂直的粗黑线就是世界坐标系的XY轴, 你的眼睛会正对着这个世界坐标系平面看.
现在三维box的底面(红色面)正好贴在世界坐标系的Z轴为0的深度上。相当于你的眼睛跟物体零距离. 因此你得把这个Box向Z轴的负方向走上-1个或者更多个,才可以看见这个Box.

这段程序的运行效果如下:

平移

旋转

缩放
原创文章,出自"博客园, 猪悟能'S博客" : http://www.cnblogs.com/hackpig/
SharpGL学习笔记(二) 模型变换(几何变换)的更多相关文章
- SharpGL学习笔记(七) OpenGL的变换总结
笔者接触OpenGL最大的困难是: 经常调试一份代码时, 屏幕漆黑一片, 也不知道结果对不对,不知道如何是好! 这其实就是关于OpenGL"变换"的基础概念没有掌握好, 以至于对& ...
- WPF的Binding学习笔记(二)
原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...
- AJax 学习笔记二(onreadystatechange的作用)
AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...
- [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计
源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...
- JMX学习笔记(二)-Notification
Notification通知,也可理解为消息,有通知,必然有发送通知的广播,JMX这里采用了一种订阅的方式,类似于观察者模式,注册一个观察者到广播里,当有通知时,广播通过调用观察者,逐一通知. 这里写 ...
- java之jvm学习笔记二(类装载器的体系结构)
java的class只在需要的时候才内转载入内存,并由java虚拟机的执行引擎来执行,而执行引擎从总的来说主要的执行方式分为四种, 第一种,一次性解释代码,也就是当字节码转载到内存后,每次需要都会重新 ...
- Java IO学习笔记二
Java IO学习笔记二 流的概念 在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成. 程序中的输入输 ...
- 《SQL必知必会》学习笔记二)
<SQL必知必会>学习笔记(二) 咱们接着上一篇的内容继续.这一篇主要回顾子查询,联合查询,复制表这三类内容. 上一部分基本上都是简单的Select查询,即从单个数据库表中检索数据的单条语 ...
- NumPy学习笔记 二
NumPy学习笔记 二 <NumPy学习笔记>系列将记录学习NumPy过程中的动手笔记,前期的参考书是<Python数据分析基础教程 NumPy学习指南>第二版.<数学分 ...
随机推荐
- Jedis客户端操作redis缓存命令详解
1.对value操作的命令 exists(key):确认一个key是否存在 del(key):删除一个key type(key):返回值的类型 keys(pattern):返回满足给定pattern的 ...
- mysql 类型
1.bigint 范围(-2^63 (-9223372036854775808) 到 2^63-1 (9223372036854775807) ) 字节大小(8个字节) 2.int 范围(-2^31 ...
- swift闭包的另一种用法
这不是教程. 当你碰到函数参数需要传递一个闭包(closure)时,一般是可以直接这么传递的(假定无返回): // 教程一般教你在参数位置传递closure: someMethod(arg1, arg ...
- Android开发学习笔记-GridView的动态显示
1.添加GridItem布局文件 <?xml version="1.0" encoding="utf-8"?> <LinearLayout x ...
- springmvc+freemarker生成静态html文件
参考资料: http://mylfd.iteye.com/blog/1896501 http://www.cnblogs.com/xxt19970908/p/5553045.html 个人实践: 1. ...
- linux中sudo如何读取标准输入作为密码,避免每次都输入密码?
需求描述: 今天想要在生产环境中,弄自动部署的脚本,但是现在呢,需要sudo权限,每次都要输入.就想看sudo如何能从标准输入读取密码. 操作过程: 1.原来的方法 [deployer@testvm ...
- arcview、arcinfo、arceditor的区别
arcview = 交互式制图+地图设计和输出+基于地图的查询+直接读取数据+地理处理框架+定制应用程序框架 arceditor = arcview + geodatabase定义.管理和编辑 arc ...
- OpenSift源代码编译过程记录
本文记录了在CentOS6.5上编译Sift的开源实现OpenSift的编译过程,同一时候记录了编译过程中的几个问题. sift的理论已经有非常多了,以下会给出链接: 1.Requirements a ...
- PHP从数组中找到指定元素的位置
群里有人问,有个数组五个元素 分为1到5 现在要求 循环找出3元素的索引,怎么做性能才是最高. 我不知道哪个性能最高,但是我想提出可以用多种方式进行查找,然后进行比较选择. 我想,最简单最基础的 应 ...
- 解决SOCKET通信 ERROR_INSUFFICIENT_BUFFER错误
错误发生在服务端异步收到一个socket连接,之后使用WSAGetLastError()得到的IO错误码是122 这个错误码在系统中的解释是The data area passed to a syst ...