[OSG]矩阵运算
我们都知道,OpenGL规定矩阵使用列主序存储,即glLoadMatrix等函数要求输入的数组是按列主序存储的矩阵。然而,一个很奇怪的事实是,OSG中矩阵存储是使用的标准C二维数组(行主序),并且也是直接将行主序存储的矩阵元素作为参数传递给glLoadMatrix调用的。
另外一个奇怪的事实是,OpenGL规定的对顶点应用矩阵变换使用左乘(即把顶点坐标看做列向量,变换写做M*P),而OSG规定使用右乘(即把顶点坐标看作行向量,变换写做P*M)。
然而,这两个奇怪的事实绝不是OSG设计上的失误,而是有意为之!
在了解OSG的这一设计的目的及原理之前,先回忆一下矩阵运算的一些基础知识。
我们知道,把一个一维向量看做行向量与看做列向量,从几何意义上来讲是没有差别的,但是,对它们进行相同的空间变换(平移、旋转),所需要的变换矩阵却是不同的(它们互为转置)。通常情况下,我们习惯把顶点坐标看待成行向量,即矩阵变换为V*M,因为在此情况下的平移矩阵是我们所习惯看到的
,而对于列向量的平移矩阵则是
。
然而,由于OpenGL规定对顶点的矩阵变换使用左乘,即顶点坐标被看做列向量。
为了使引擎的使用者能够面向形如
的平移矩阵,OSG做了这样的设计:首先,由于在矩阵变换应用顺序上与OpenGL使用了相反的规定(OSG的右乘对OpenGL的左乘),导致OSG计算得到的矩阵正好是OpenGL需要的矩阵的转置;然后,和在矩阵元素传递上再次使用了与OpenGL相反的规定(OSG的行主序对OpenGL的列主序),由于对同一个一维数组按行主序解析与按列主序解析得到的矩阵正好互为转置,所以OSG传递给OpenGL的矩阵被再一次转置;两次转置相抵消,使得最终OpenGL收到的矩阵正是引擎调用者所理解的矩阵。
以上对OSG设计动机的解释纯属个人理解,重点在于对其计算逻辑正确性的推理。
接下来说一下OSG中矩阵运算规则:
- 上文已经指出,OSG矩阵变换使用如下公式:V' = V * M 其中,V是变换前的节点坐标,M是变换矩阵,V'是变换后的节点坐标,三者均为世界坐标系下的表示。
- 设变换矩阵M由M1、M2两个变换矩阵组合而成,即 M = M1 * M2,则 V'= V * M1 * M2,对应到OSG节点树结构,则是:MT2->MT1->GEODE。
对于变换几何意义的理解,可以以从左向右(矩阵相乘)/从下向上(节点树结构)的顺序,此时每个变换都是以世界坐标系为参考的;也可以以从右向左/从上向下的顺序理解,此时变换都是以模型坐标系(变换过程中的临时坐标系)为参考的。 - 对于平移T、旋转R、缩放S三种变换矩阵的组合,应该按如下顺序:M = S * R * T。
- 变换矩阵与坐标系的关系,已知变换矩阵
,则变换矩阵对应的坐标系的三个坐标轴为
[OSG]矩阵运算的更多相关文章
- osg实例介绍
osg实例介绍 转自:http://blog.csdn.net/yungis/article/list/1 [原]osgmotionblur例子 该例子演示了运动模糊的效果.一下内容是转自网上的:原理 ...
- osg 笔记一 (转)
场景图形采用一种自顶向下的,分层的树状数据结构来组织空间数据集,以提高渲染的效率 场景图形树结构的顶部是一个根节点,从根节点向下延伸,各个组节点中均包含了几何信息和用于控制其外观的渲染状态信息.根节点 ...
- OSG的组成结构
OSG的组成结构 核心结构 OSG的功能类采用“命名空间+类名称”的形式来命名.命名空间的命名方式为:第一个单词小写,后继单词的首字母大写,例如osg.osgUtil.osgViewer等:类的名称则 ...
- OSG计时器与时间戳
static osg::Timer* sendMsgTimer = new osg::Timer; if (sendMsgTimer->time_m()>100)//100ms {// d ...
- OSG消息机制之消息分析
OSG消息接收在头文件有各种事件的相关参数
- OSG消息机制之事件处理概述
OSG的消息机制包括好多个头文件预定义及多个类. 首先,消息接收相关的类当属osgGA::GUIEventHandler和osgGA::GUIEventAdapter这两个类了.前者处理OSG程序与用 ...
- OSG 3D场景渲染编程概述
OSG是Open Scene Graphic的缩写,是基于C++平台的使用OpenGL技术的开源3D场景开发. vs环境安装或者是在Ubuntu中环境的安装网上教程很多,都是大同小异的,认真操作容易成 ...
- OSG透明代码
//关闭灯光 state->setMode(GL_LIGHTING,osg::StateAttribute::OFF|osg::StateAttribute::PROTECTED); //打开混 ...
- [Python学习] python 科学计算库NumPy—矩阵运算
NumPy库的核心是矩阵及其运算. 使用array()函数可以将python的array_like数据转变成数组形式,使用matrix()函数转变成矩阵形式. 基于习惯,在实际使用中较常用array而 ...
随机推荐
- GridView 实现LinkButton下载文件/附件
<asp:TemplateField > <ItemTemplate> <asp:LinkButton ID="lbtnDownFile" runat ...
- Unity WebGL MoonSharp崩溃问题
当前Unity的代码更新方案基本都选择的ULua,而我们项目还需要考虑Web平台,ULua不支持WebGL,所以决定选择MoonSharp.MoonSharp(http://www.moonsharp ...
- VMware安装chrome os遇到选择网络问题.
在下载下来的vmx文件中添加一行ethernet0.virtualDev = "e1000" 就可以了.参考网站http://communities.vmware.com/thre ...
- DataTable数据赋值给Model通用方法
注:该文属本人原创,今后项目中发现该方法存在BUG会实时更新,转载记得附上原文出处,方便大家获得最新代码. 相信大家在做项目中,经常会根据不同的表new各种不同的Model,当需要对Model进行实例 ...
- LintCode Longest Common Substring
原题链接在这里:http://www.lintcode.com/en/problem/longest-common-substring/# 题目: Given two strings, find th ...
- 第五篇:白话tornado源码之褪去模板的外衣
上一篇<白话tornado源码之请求来了>介绍了客户端请求在tornado框架中的生命周期,其本质就是利用epoll和socket来获取并处理请求.在上一篇的内容中,我们只是给客户端返回了 ...
- android获取textview的行数
最近项目需求,需要获取Textview的行数,通过行数与TextView的maxLines进行比较来确定是否显示TextView下方的展开按钮是否显示,废话少说直接上代码,mTextView.getL ...
- python之路 目录
目录 python python_基础总结1 python由来 字符编码 注释 pyc文件 python变量 导入模块 获取用户输入 流程控制if while python 基础2 编码转换 pych ...
- sed 引入shell变量
双单引号即可 1.eval sed ’s/$a/$b/’ filename2.sed "s/$a/$b/" filename3.sed ’s/’$a’/’$b’/’ filenam ...
- 扩展映射 Diffusion maps
Diffusion maps接触到扩展映射,高维数据降维的相关东西. 扩展映射是一种非线性方法.