文档章节

OpenGL的列向量和OSG的行向量

哈全文
 哈全文
发布于 2017/06/03 20:46
字数 1967
阅读 14
收藏 0
点赞 0
评论 0

在我们使用OpenGL和OSG的过程中,总会涉及到顶点坐标以及坐标的变换(通过向量和矩阵相乘),这其中经常会看到有人说在OpenGL中使用的是列向量,在OSG中使用的是行向量 ,由于行向量和列向量的不同导致在矩阵作乘法的时候有左乘和右乘之分,本文就这一问题作一个相对完整的解释。

 

 

  • 行向量和列向量

1.  行向量和列向量的定义如下:

在线性代数中,行向量是一个 1×n的矩阵, 即矩阵由一个含有n个元素的行所组成。 

在线性代数中,列向量是一个 n×1 的矩阵,即矩阵由一个含有n个元素的列所组成。 

 

2. 左乘和右乘

说简单点,左乘(又称前乘)就是乘在左边(即乘号前),右乘(又称后乘)就是乘在右边(即乘号后)。比如说,A左乘E即AE,A右乘E即EA。

 

3.行向量和列向量的变换

由于向量实际上是某一维度为1的矩阵,那么根据矩阵乘法的规则,会出现下面的情况:

(1)行向量左乘矩阵

在图形学中一般矩阵都是4x4的,行向量一般设置为1x4的矩阵(齐次坐标)。当行向量左乘矩阵的时候 (1x4)* (4x4)得到的是一个1x4的行向量

(2)行向量右乘矩阵

这种情况,也就是(4x4)*(1x4),根据矩阵相乘的规则,这是不允许的

(3)列向量左乘矩阵

这种情况,也就是(4x1)*(4x4),根据矩阵相乘规则,这也是不允许的

(4)列向量右乘矩阵

这种情况,也就是(4x4)*(4x1),得到的是一个4x1的行向量

 

我们作三维的变化为的就是将一个坐标变换到另一个坐标,于是上面讨论的(1)(4)两种方式正好符合这一要求。根据上面的讨论有以下的结论:

行向量左乘还是右乘根本就是矩阵乘法规则的限制,行向量只能左乘而列向量只能右乘矩阵,这和三维图形学没有一点儿的关系。因此有人说OpenGL都是右乘、OSG都是左乘从结论上来说是对的,但是这和OpenGL以及OSG本身并没有半点关系,这只是矩阵乘法的定义。

 

 

  • 行向量列向量以及在编程语言中的内存布局

假设有一个4x4的矩阵M,我们现在有一个顶点的坐标是v,通过M矩阵的变换可以把它变为v’,现在分别假设 v是行向量或者v是列向量,于是有以下两种情形:

(1)v是行向量 , 那么  v' = v*M  

(2)v是列向量,  那么  v' = M*v  

用那种方式来理解变换都是可以的。下面一段是OpenGL规范最早的设计者的一段话,可以从中知道他当时只是想使用列向量这种方式让图形学和数学上的表达一致,而" 欺骗” 读者说OpenGL使用的是列向量。

I'm the one responsible for the 'column-major ordering' used in OpenGL, so I'll try to explain what's going on to try to put this discussion to rest.

First, there are two issues that seem to be confused. 
One issue is how matrices are stored in memory, 
and the other is whether one treats vectors as rows of coordinates or as columns.

I'll dispense with the second issue first. 
Recent mathematical treatments of linear algebra and related fields invariably treat vectors as columns (there are some technical reasons for this). For some reason, this has not been the case in computer graphics, where vectors were written as rows, thus transposing everything from standard mathematical usage. When I wrote the OpenGL spec, I decided to do my part to right this heinous inconsistency. Thus the spec is written with vectors treated as columns, with a matrix correspondingly applied on the left of a column.

The one difficulty was compatibility with the current GL, where vectors had been written as rows. So I come up with this subterfuge: say that matrices in OpenGL are stored in column major order. The point is that you could rewrite the spec with everything transposed (with vectors written as rows), and everything would be exactly the same as it was, including the row major ordering of matrices.

那么现在又有一个疑问:既然行向量和列向量并没有什么不同,那么为什么大家都在说在OpenGL中使用的是列向量而OSG中使用的是行向量呢? 答案就在于:当使用C/C++语言进行描述矩阵和向量相乘的时候,使用行向量的理解方式和使用列向量的理解方式在内存中存储矩阵元素的时候有所不同,这就是真正的关键点所在。还是按之前的做法,假设现在坐标点是  (1,2,3, 0),通过矩阵M,变换为坐标值是(38,44,50,56)的点,对于这个变换来说,可以使用行向量和列向量来理解,这两种理解方式正好就是OSG和OpenGL的处理方式。

 

(1)使用行向量的方式来理解, 那么我们的矩阵是 

    double M[4][4] = 
    {
        {1, 2, 3, 4},
        {5, 6, 7, 8},
        {9,10,11,12},
        {13,14,15,16}
    };

通过矩阵乘法知道 v = (1, 2, 3, 0) , 那么 v' = vM = (38, 44, 50, 56), 假设正好我们使用C/C++语言进行编码,由于C/C++语言中并没有矩阵这种类型,它使用二维数组来存储矩阵元素,并且在C/C++中使用的是 行主序的方式进行存储的,因此矩阵M在内存中如下图所示:


 

(2)使用列向量的方式来理解,那么我们的矩阵就不是上面的矩阵了,而是:

    double M[4][4] = 
    {
        {1, 5, 9,  13},
        {2, 6, 10, 14},
        {3, 7, 11, 15},
        {4, 8, 12, 16}
    };

 

通过矩阵乘法,v' = Mv

在C/C++内存模型中,这个矩阵M如下所示:

 

可以看到使用行向量和列向量的区别,仅仅是内存布局的不同导致我们在理解行向量和列向量的时候有差异。

 

从上面的分析可以得出以下的几点结论:

 

(1)使用行向量或者列向量来理解OpenGL和OSG都可以,实际上行向量和列向量并没有任何的差别

(2)当使用列向量来理解变换的时候,所有的变换方式都是后乘(右乘),当使用行向量来理解变换的时候,所有变换的方式都是前乘(左乘)

(3)OpenGL为了表现它是使用的列向量,所有的矩阵设计为列主序的方式,因此当我们在进行变换的时候,需要注意要将矩阵按C/C++语言内存布局的方式存储,也就是说假设有一个平移矩阵,平移量Tx,Ty,Tz应该处在的位置是数组的第 4,8,12位置处

这种处理方式在C/C++中会显得十分别扭,因为这几个平移变量的位置不连续,这也是为什么很多三维库都使用 行主序(行向量)方式的原因,因为如果使用行向量的方式,那么这三个行向量的位置正好是相邻的,和C/C++语言的存储方式一致。  不过OpenGL也提供了用来接收行主序方式的矩阵的函数:

glLoadTransposeMatrixf

glLoadTransposeMatrixd

 

(4)OSG为了让人感觉它使用的是行向量,所有矩阵的设计都是基于行主序的方式。这样的设计正好与c++语言中二维数组的存储方式一致,使用起来比较自然。所有在OSG中的变换都是左乘矩阵, 通过查看OSG中Matrix的实现也很容易看到这一点:

    double xarray[4][4] = 
    {
        {1, 2, 3,  4},
        {5, 6, 7, 8},
        {9, 10, 11, 12},
        {13, 14, 15, 16}
    };

    osg::Matrixd mat;
    mat.set((double*)xarray);

    //x12 = 7
    double x12 = mat(1, 2);

本文转载自:http://blog.csdn.net/csxiaoshui/article/details/51740882

共有 人打赏支持
哈全文
粉丝 14
博文 92
码字总数 22122
作品 0
海淀
其他
OpenGL超级宝典笔记——操作矩阵

为了更强大的功能和灵活性,我们有时需要直接操作矩阵。在OpenGL中4x4的矩阵用包含16个浮点数值的一维数组来表示,而不是用二维的4x4的数组来表示。OpenGL之所以这么做,因为使用一维数组更高...

Mario_Q
2013/09/24
0
0
mac上学用opengl(5)-光照

光照系统: 光源 材质 光照环境 镜面反射+漫反射 法线向量 每个顶点有个法线向量,只要指定每一个顶点的法线向量,OpenGL会自行计算顶点之间的其它点的法线向量。 glColor函数指定颜色 glNo...

openlab
2013/10/08
0
0
3D坐标系、矩阵变换、视景体与裁剪

背景 当前3D图形界主要有两个:微软的Direct 3D以及某组织的OpenGL。曾经一度OpenGL几乎占据所有3D图形领域,这在巨人微软面前简直就是屌丝逆袭。曾几何时微软搞IDE borland公式倒闭了,后来...

乐观的vc
2013/04/14
0
0
OpenGL超级宝典笔记——使用光源

使用光源 要模拟真实世界,仅有环境光是不够的,需要指定更多的光源来提升真实感。OpenGL至少提供8种光源,可以在场景中的任意位置甚至是可视区域之外。你可以指定光源位于无限远处以获得平行...

Mario_Q
2013/10/10
0
4
OpenGL 做demo会用到

说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640*480分辨率、16色来做吗?显然是不行的。 本帖...

Simon253
2013/01/31
0
2
OpenGL学习之路19---- 聚光灯光源

代码在github上 根据教程:ogldev一步步开始,记录学习历程 聚光灯光源 聚光灯光源是结合了平行光方向的特性和点光源随距离衰减的特性,并且离光源越远,照亮圆形区域越大,即光源呈锥形。 ...

zach_z
05/12
0
0
OpenGL学习之路4----使用着色器(shader)

根据教程:ogldev一步步从零开始,记录学习历程 一、OpenGL 渲染管线 这节相比上一节有了本质上的区别,OpenGL实际上是通过渲染管线(rendering pipeline),经过一系列的数据处理,将应用程序的...

zach_z
04/23
0
0
ubuntu12.04下安装opengl

前言 OpenGL 是一套由SGI公司发展出来的绘图函式库,它是一组 C 语言的函式,用于 2D 与 3D 图形应用程式的开发上。 OpenGL 让程式开发人员不需要考虑到各种显示卡底层运作是否相同的问题,硬...

guoliang
2014/02/27
0
0
OpenGL学习之路2----画一个点

根据教程:ogldev一步步从零开始,记录学习历程 一、简述 这一节比上一节《打开一个窗口》,多了需要使用glew库和3d数学库 glew是OpenGL的扩展库,用于帮助C/C++开发者初始化扩展(OpenGL扩展...

zach_z
04/23
0
0
OpenGL开发之旅基础知识介绍

OpenGL开发之旅基础知识介绍 glLoadIdentity();gluortho2D(-1.0,1.0,-1.0,1.0) glEnd(); glPushMatrix();glPopMatrix(); 0000FF;">void) { // 清除颜色缓冲区 glClear(GLCOLORBUFFERBIT); /......

andyhe91
2013/05/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

崛起于Springboot2.X之thymeleaf(24)

1、依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId></dependency> 2、application.properties spring......

木九天
9分钟前
0
0
spring-boot:run启动时,指定spring.profiles.active

Maven启动指定Profile通过-P,如mvn spring-boot:run -Ptest,但这是Maven的Profile。 如果要指定spring-boot的spring.profiles.active,则必须使用mvn spring-boot:run -Drun.profiles=test......

夜黑人模糊灬
11分钟前
0
0
大数据分析挖掘技术学习:Python文本分类

引言 文本分类作为自然语言处理任务之一,被广泛应用于解决各种商业领域的问题。文本分类的目的是将 文本/文档 自动地归类为一种或多种预定义的类别。常见的文本分类应用如下: • 理解社交媒...

加米谷大数据
15分钟前
0
0
istio-0.8 指标监控,prometheus,grafana

配置: https://istio.io/docs/tasks/telemetry/metrics-logs/ https://istio.io/docs/tasks/telemetry/tcp-metrics/ envoy拦截请求>上报mixer>对接prometheus>grafana 效果截图: promethe......

xiaomin0322
17分钟前
0
0
公众号推荐

阿里技术 书籍:《不止代码》

courtzjl
20分钟前
0
0
关于改进工作效率

1.给不同的业务线建立需求群,所有的数据需求都在群里面提。 2.对于特别难搞定的事情,到对应的技术哪去做,有问题随时沟通。 3.定期给工作总结形成方法论。 4.学习新的技术,尝试用新的方法...

Avner
27分钟前
0
0
关于thinkphp 框架开启路径重写,无法获取Authorization Header

今天遇到在thinkphp框架中获取不到header头里边的 Authorization ,后来在.htaccess里面加多一项解决,记录下: <IfModule mod_rewrite.c> Options +FollowSymlinks -Multiviews Rewrite......

殘留回憶
31分钟前
0
0
centos 使用yum安装nginx后如何添加模块 10

centos 使用yum安装nginx后如何添加模块 10 centos6.2版本,使用yum来安装了nginx,但是最近需要重新添加模块,所以就傻了,询问下有人知道怎么重新添加模块吗? PS:俺是新手,需要高手救助...

linjin200
34分钟前
1
0
dubbo 资料

dubbo资料网站: https://www.cnblogs.com/a8457013/p/7818925.html

zaolonglei
34分钟前
0
0
大型网站,你是如何架构的?

大型网站,你是如何架构的?

微小宝
36分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部