openGL 坐标系的互相转换

openGL坐标系包括旋转,平移,缩放被塞在一个矩阵里面。

坐标系之间的转换基础是矩阵的运算。

每个矩阵代表的坐标系,就是是原点坐标系通过旋转。平移,缩放得到的坐标系。

当一个矩阵右乘一个向量或是还有一个矩阵,意味着把右边的变换。变成相对于左边的矩阵坐标系之上。

假设把一个世界坐标的X转换到一个矩阵上,我们能够矩阵右乘这个坐标:

static float multiplyMX(Matrix4* matrix, float x) {
	return matrix->m[0] * x + matrix->m[4] + matrix->m[8] + matrix->m[12];
}

假设把一个世界坐标Y转换到一个矩阵上。我们能够矩阵右乘这个坐标:

static float multiplyMY(Matrix4* matrix, float y) {
	return matrix->m[1] + matrix->m[5] * y + matrix->m[9] + matrix->m[13];
}

假设把一个世界坐标点转换到一个矩阵上,我们能够矩阵右乘这个点:

static void multiplyMV4(Matrix4* matrix, float x, float y, float z, float w, Out(Vector4* result)) {
	result->v[0] = matrix->m[0] * x + matrix->m[4] * y + matrix->m[8]  * z + matrix->m[12] * w;
	result->v[1] = matrix->m[1] * x + matrix->m[5] * y + matrix->m[9]  * z + matrix->m[13] * w;
	result->v[2] = matrix->m[2] * x + matrix->m[6] * y + matrix->m[10] * z + matrix->m[14] * w;
	result->v[3] = matrix->m[3] * x + matrix->m[7] * y + matrix->m[11] * z + matrix->m[15] * w;
}

static void multiplyMV3(Matrix4* matrix, float x, float y, float z, Out(Vector3* result)) {
	result->v[0] = matrix->m[0] * x + matrix->m[4] * y + matrix->m[8]  * z + matrix->m[12];
	result->v[1] = matrix->m[1] * x + matrix->m[5] * y + matrix->m[9]  * z + matrix->m[13];
	result->v[2] = matrix->m[2] * x + matrix->m[6] * y + matrix->m[10] * z + matrix->m[14];
}

static void multiplyMV2(Matrix4* matrix, float x, float y, Out(Vector2* result)) {
	result->v[0] = matrix->m[0] * x + matrix->m[4] * y + matrix->m[8] + matrix->m[12];
	result->v[1] = matrix->m[1] * x + matrix->m[5] * y + matrix->m[9] + matrix->m[13];
}

假设把一个世界坐标系转换到一个矩阵上,我们矩阵右乘这个矩阵:

static void multiplyMM(Matrix4* left, Matrix4* right, Out(Matrix4* result)) {
  result->m[0]  = left->m[0] * right->m[0]  + left->m[4] * right->m[1]  + left->m[8]  * right->m[2]  + left->m[12] * right->m[3];
  result->m[1]  = left->m[1] * right->m[0]  + left->m[5] * right->m[1]  + left->m[9]  * right->m[2]  + left->m[13] * right->m[3];
  result->m[2]  = left->m[2] * right->m[0]  + left->m[6] * right->m[1]  + left->m[10] * right->m[2]  + left->m[14] * right->m[3];
  result->m[3]  = left->m[3] * right->m[0]  + left->m[7] * right->m[1]  + left->m[11] * right->m[2]  + left->m[15] * right->m[3];

  result->m[4]  = left->m[0] * right->m[4]  + left->m[4] * right->m[5]  + left->m[8]  * right->m[6]  + left->m[12] * right->m[7];
  result->m[5]  = left->m[1] * right->m[4]  + left->m[5] * right->m[5]  + left->m[9]  * right->m[6]  + left->m[13] * right->m[7];
  result->m[6]  = left->m[2] * right->m[4]  + left->m[6] * right->m[5]  + left->m[10] * right->m[6]  + left->m[14] * right->m[7];
  result->m[7]  = left->m[3] * right->m[4]  + left->m[7] * right->m[5]  + left->m[11] * right->m[6]  + left->m[15] * right->m[7];

  result->m[8]  = left->m[0] * right->m[8]  + left->m[4] * right->m[9]  + left->m[8]  * right->m[10] + left->m[12] * right->m[11];
  result->m[9]  = left->m[1] * right->m[8]  + left->m[5] * right->m[9]  + left->m[9]  * right->m[10] + left->m[13] * right->m[11];
  result->m[10] = left->m[2] * right->m[8]  + left->m[6] * right->m[9]  + left->m[10] * right->m[10] + left->m[14] * right->m[11];
  result->m[11] = left->m[3] * right->m[8]  + left->m[7] * right->m[9]  + left->m[11] * right->m[10] + left->m[15] * right->m[11];

  result->m[12] = left->m[0] * right->m[12] + left->m[4] * right->m[13] + left->m[8]  * right->m[14] + left->m[12] * right->m[15];
  result->m[13] = left->m[1] * right->m[12] + left->m[5] * right->m[13] + left->m[9]  * right->m[14] + left->m[13] * right->m[15];
  result->m[14] = left->m[2] * right->m[12] + left->m[6] * right->m[13] + left->m[10] * right->m[14] + left->m[14] * right->m[15];
  result->m[15] = left->m[3] * right->m[12] + left->m[7] * right->m[13] + left->m[11] * right->m[14] + left->m[15] * right->m[15];
}

这就是利用矩阵, 把一个世界坐标系的坐标,转换到局部坐标系的方法。

那么。怎样把一个局部坐标系转换到世界坐标系呢?

这里须要得到局部坐标系相应矩阵的逆矩阵,这个矩阵包括了还原矩阵操作的变换。

然后,把逆矩阵当做左边的矩阵,去右乘局部坐标点, 我们就能够得到局部坐标变成世界坐标后的坐标。

static bool tryInvert(Matrix4* matrix, Out(Matrix4* result)) {
    float a0 = matrix->m[0]  * matrix->m[5]  - matrix->m[1]  * matrix->m[4];
    float a1 = matrix->m[0]  * matrix->m[6]  - matrix->m[2]  * matrix->m[4];
    float a2 = matrix->m[0]  * matrix->m[7]  - matrix->m[3]  * matrix->m[4];
    float a3 = matrix->m[1]  * matrix->m[6]  - matrix->m[2]  * matrix->m[5];
    float a4 = matrix->m[1]  * matrix->m[7]  - matrix->m[3]  * matrix->m[5];
    float a5 = matrix->m[2]  * matrix->m[7]  - matrix->m[3]  * matrix->m[6];

    float b0 = matrix->m[8]  * matrix->m[13] - matrix->m[9]  * matrix->m[12];
    float b1 = matrix->m[8]  * matrix->m[14] - matrix->m[10] * matrix->m[12];
    float b2 = matrix->m[8]  * matrix->m[15] - matrix->m[11] * matrix->m[12];
    float b3 = matrix->m[9]  * matrix->m[14] - matrix->m[10] * matrix->m[13];
    float b4 = matrix->m[9]  * matrix->m[15] - matrix->m[11] * matrix->m[13];
    float b5 = matrix->m[10] * matrix->m[15] - matrix->m[11] * matrix->m[14];

    // Calculate the determinant.
    float det = a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;

    // Close to zero, can‘t invert.
    if (fabs(det) < FLT_EPSILON) {
    	 return false;
	}

    float scalar   = 1.0f / det;

    // Support the case where matrix == result

    result->m[0]   = ( matrix->m[5]  * b5 - matrix->m[6]  * b4 + matrix->m[7]  * b3) * scalar;
    result->m[1]   = (-matrix->m[1]  * b5 + matrix->m[2]  * b4 - matrix->m[3]  * b3) * scalar;
    result->m[2]   = ( matrix->m[13] * a5 - matrix->m[14] * a4 + matrix->m[15] * a3) * scalar;
    result->m[3]   = (-matrix->m[9]  * a5 + matrix->m[10] * a4 - matrix->m[11] * a3) * scalar;

    result->m[4]   = (-matrix->m[4]  * b5 + matrix->m[6]  * b2 - matrix->m[7]  * b1) * scalar;
    result->m[5]   = ( matrix->m[0]  * b5 - matrix->m[2]  * b2 + matrix->m[3]  * b1) * scalar;
    result->m[6]   = (-matrix->m[12] * a5 + matrix->m[14] * a2 - matrix->m[15] * a1) * scalar;
    result->m[7]   = ( matrix->m[8]  * a5 - matrix->m[10] * a2 + matrix->m[11] * a1) * scalar;

    result->m[8]   = ( matrix->m[4]  * b4 - matrix->m[5]  * b2 + matrix->m[7]  * b0) * scalar;
    result->m[9]   = (-matrix->m[0]  * b4 + matrix->m[1]  * b2 - matrix->m[3]  * b0) * scalar;
    result->m[10]  = ( matrix->m[12] * a4 - matrix->m[13] * a2 + matrix->m[15] * a0) * scalar;
    result->m[11]  = (-matrix->m[8]  * a4 + matrix->m[9]  * a2 - matrix->m[11] * a0) * scalar;

    result->m[12]  = (-matrix->m[4]  * b3 + matrix->m[5]  * b1 - matrix->m[6]  * b0) * scalar;
    result->m[13]  = ( matrix->m[0]  * b3 - matrix->m[1]  * b1 + matrix->m[2]  * b0) * scalar;
    result->m[14]  = (-matrix->m[12] * a3 + matrix->m[13] * a1 - matrix->m[14] * a0) * scalar;
    result->m[15]  = ( matrix->m[8]  * a3 - matrix->m[9]  * a1 + matrix->m[10] * a0) * scalar;

    return true;
}

是的有些矩阵是没有逆矩阵的,所以求逆矩阵的操作会失败。

世界坐标系的意义,就是坐标是相对于原点坐标系的。

局部坐标系的意义。就是坐标不是相对于原点坐标系。而是相对于某个详细的坐标系。

局部坐标系是能够通过上面的方法互相转换的。

那么怎样在局部坐标系之间互相转换呢?

我们无法把一个局部坐标系的坐标,一次就变化成还有一个局部坐标系上。

由于两个不同的局部坐标的坐标。都是相对于各自的坐标系。也就是參考系不同。

但。我们能够,把一个局部坐标系,转换到世界坐标系。以后再从世界坐标系转换到还有一个局部坐标系上。

坐标系转换的意义是什么?

假设我们可以恰当的选取坐标系。在进行坐标计算的时候,会简化非常多运算和思考的模型。

由于一个物体坐标的变化总是在父类坐标之内的,也就是相对于父类坐标系去变化。

这个父类坐标系。要么世界坐标系,要么就是某个详细的坐标系。

而我们这里讨论的坐标转换的模型是这种。

一个坐标终于呈如今屏幕上,我们假设改动了坐标的父坐标系,通过坐标系的转化。而保持这个坐标终于呈现的位置不变。

打一个例如

假设一个坐标(0, 0)在世界坐标系上,终于呈现出来的就是在(0, 0)点处。

我们如今把这个坐标,放到一个在(5, 5)处的坐标系内。这样这个坐标全部的数值都像相对于(5, 5)这个坐标系的。

那么,(0, 0)终于呈现的就是在(5, 5)处了,而不再原来的位置。

我们通过把这个坐标(0, 0)转换到(5, 5)的坐标系里,会得到新的坐标(-5, -5)这是相对于新坐标系的数值。

终于(-5, -5) 会呈如今(0, 0)的位置。

其实,在openGL绘制的时候。我们常常须要在各种不同的坐标系之间互相转换,可能是为了计算动画。可能是为了计算物理碰撞。

时间: 2024-10-24 14:36:28

openGL 坐标系的互相转换的相关文章

Cocos2d-x的坐标系和其转换方式

1.坐标系 cocos2d使用的是opengl坐标系,这里说的cocos2d是指cocos2d中所有的节点的节点坐标系也都是使用的opengl坐标系. 手机设备使用的是标准设备坐标系,这与cocos2d无关. 2.锚点 锚点是一个相对位置,值从0-1,这是个节点的属性,按照cocos2d使用opengl坐标,右上角是(1,1)这个锚点坐标,右下角是(0,0)坐标 下面的图是重设锚点,绿色层设置位置为(0,0),在红色层添加绿色层: 每个节点有一个忽略锚点的属性,如果设置为true,则节点锚点强制

[OpenGL]OpenGL坐标系及坐标转换

OpenGL通过相机模拟.可以实现计算机图形学中最基本的三维变换,即几何变换(模型变换-视图变换(两者合称几何变换)).投影变换.裁剪变换.视口变换等,同时,OpenGL还实现了矩阵堆栈等.理解掌握了有关坐标变换的内容,就算真正走进了精彩地三维世界. 坐标系统 世界坐标系:在现实世界中,所有的物体都具有三维特征,但计算机本身只能处理数字,显示二维的图形,将三维物体及二维数据联系在一起的唯一纽带就是坐标.为了使被显示的三维物体数字化,要在被显示的物体所在的空间中定义一个坐标系.这个坐标系的长度单位

Win窗口坐标二维坐标与OpenGl的世界坐标系的转换

Win窗口坐标二维坐标与OpenGl的世界坐标系的转换 1. 首先明白Win环境的窗口二维坐标系表示 即,Win的屏幕坐标的坐标系表示如下:左上为坐标系原点,正右为X轴正方向, 正下方为Y轴正方向.    2. 在了解一下Opengl的视口坐标系 Opengl设置视口操作如下: glViewport(0,0,m_wide,m_heigth); 3. 关于opengl的世界坐标系,用户坐标系,模型坐标系可以查看博客 http://www.cnblogs.com/icmzn/p/5003600.ht

OpenGL坐标系介绍

OpenGL坐标系介绍 OpenGL可以分成四种坐标系,分别是世界坐标系,模型坐标系,眼坐标系,设备坐标系. 数学的观点:向量空间和仿射空间 仿射空间(affine space)是向量空间的扩展,除了标量和向量,它还包含另外一种对象-点. 尽管在仿射空间中对两个点以及一个点和一个标量没有定义运算,但对一个向量和一个点定义了一种运算--向量-点加法,它的结果是一个点.也可以说有一种称为点-点减法的运算,这种运算由两个点得到一个向量. 计算机科学的观点 把标量.点和向量看做是集合中的元素,并且可以按

第五讲:OpenGL坐标系和UIKit坐标系、锚点、addChild函数详解

一.坐标系 OpenGl坐标系 原点在左下角(0,0),与数据的二维坐标系一致 UIKit坐标系 又称为屏幕坐标系,原点在左上角,X轴越右越大,Y轴越下越大: 由OpenGL转化为UIKit的方法: CCPoint point = CCDirector::sharedDirector()->convertToUI(sp1->getPosition); 二.锚点 锚点默认为(0.5,0.5) 就是在精灵的中间 : *****坐标系已锚点定位(先确定锚点在哪,ccp(X,Y)是描述锚点在哪个位置)

多种坐标系之间的转换 Proj.NET和DotSpatial

Proj.NET ( http://projnet.codeplex.com/)是一个.NET下开源的空间参照和投影引擎,遵循OGC相关标准.负责人(Coordinators )是D_Guidi 和SharpGIS,开发者(Developers)还有codekaizen.rstuven等,这些人也是.NET下其他的开源系统如GeoAPI.NET.SharpMap等主要贡献者.License: GNU Library General Public License (LGPL). Proj.NET支

[转]百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换

注:项目中面对不同的坐标体系,在地图上显示会有不小的偏差,下面是JavaScript的转换方法. //定义一些常量 var x_PI = 3.14159265358979324 * 3000.0 / 180.0; var PI = 3.1415926535897932384626; var a = 6378245.0; var ee = 0.00669342162296594323; /** * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换 * 即 百度 转 谷歌.高德 *

世界坐标空间与观察坐标系之间的转换

1.世界坐标空间与观察坐标系之间的转换 已知:观察坐标系相对世界坐标系的u,v,w轴与起点q,将世界坐标系中一点变换到观察坐标系 使用左手坐标系推导 u = ( ux , uy , uz , 0 ) v = ( vx , vy , vz , 0 ) w = (wx , wy , wz , 0 ) q = ( qx , qy , qz , 1 ) 观察坐标系中的点可以表示为: p = au+bv+cw+q 即为 (a,b,c,1) 展开上述公式 p =  a * ux * x + a * uy *

ArcGIS中的坐标系定义与转换 (转载)

原文:ArcGIS中的坐标系定义与转换 (转载) 1.基准面概念:  GIS中的坐标系定义由基准面和地图投影两组参数确定,而基准面的定义则由特定椭球体及其对应的转换参数确定,因此欲正确定义GIS系统坐标系,首先必须弄清地球椭球体(Ellipsoid).大地基准面(Datum)及地图投影(Projection)三者的基本概念及它们之间的关系.   基准面是利用特定椭球体对特定地区地球表面的逼近,因此每个国家或地区均有各自的基准面,我们通常称谓的北京54坐标系.西安80坐标系实际上指的是我国的两个大