[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而 ...
随机推荐
- js获取上传文件个数 以及名称
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- vim - copy/paste a word
1. http://stackoverflow.com/questions/7797068/copying-a-word-and-pasting-over-a-word viwp - visually ...
- sqlalchemy mark-deleted 和 python 多继承下的方法解析顺序 MRO
sqlalchemy mark-deleted 和 python 多继承下的方法解析顺序 MRO 今天在弄一个 sqlalchemy 的数据库基类的时候,遇到了跟多继承相关的一个小问题,因此顺便看了一 ...
- Java中的Atomic包使用指南
Atomic包介绍 在Atomic包里一共有12个类,四种原子更新方式,分别是原子更新基本类型,原子更新数组,原子更新引用和原子更新字段.Atomic包里的类基本都是使用Unsafe实现的包装类. 原 ...
- 添加到SQLAgentReaderRole角色后报拒绝SELECT权限
最近有点大意,同事需要查看作业的权限,"理所当然"就将对应登录名添加到SQLAgentReaderRole角色. msdb的SQLAgentReaderRole数据库角色的成员继承 ...
- XML和JSON数据格式对比
概念 XML 扩展标记语言 (Extensible Markup Language, XML) ,用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语 ...
- XSLT简介
什么是? http://www.w3school.com.cn/xsl/xsl_intro.asp XSLT 是一种用于将 XML 文档转换为 XHTML 文档或其他 XML 文档的语言. XPath ...
- RDIFramework.NET-.NET快速信息化系统开发整合框架 【开发实例 EasyUI】之产品管理(MVC版)
RDIFramework.NET—.NET快速开发整合框架 [开发实例]之产品管理(MVC版) 接上篇:RDIFramework.NET (.NET快速信息化系统开发整合框架) [开发实例]之产品管理 ...
- Hadoop等软件常见运行问题及解决办法
Hadoop常见问题及解决办法 1.问题:java.io.IOException: Could not locate executable null\bin\winutils.exe in the ...
- REmap首次尝试--PC端
在REchart项目中,实验此网址的内容,得到若干实例 针对此我针对北京市做了若干实验 第一:绘制北京市的填充地图 代码如下: >BJqu<-mapNames("beijing& ...