行向量,列向量,行主序矩阵,列主序矩阵

 

原理: \left( A B \right) ^\mathrm{T} = B^\mathrm{T} A^\mathrm{T}

PS: 很不喜欢OGL的列矩阵方式,不过本质上是一样的。

 

v2 = v1 * ma * mb;        (dx)

v2 = mb(T) * ma(T) * v1     (ogl)

 

关于这个话题,网上有n多个版本,今天,我也来说说这个话题。
(一)首先,无论dx还是opengl,所表示的矢量和矩阵都是依据线性代数中的标准定义的:
“矩阵A与B的乘积矩阵C的第i行第j列的元素c(ij)等于A的第i行于B的第j列的对应元素乘积的和。”(实用数学手册,科学出版社,第二版)
例如c12 = a11*b11+a12*b21+a12*b13...

(二)在明确了这一点后,然后我们再看“矩阵的存储方式”,矩阵存储方式有两种,一种是“行主序(row-major order)/行优先”,另一种就是“列主序(column-major order)/列优先”
1)Direct3D 采用行主序存储

“Effect matrix parameters and HLSL matrix variables can define whether the value is a row-major or column-major matrix; however, the DirectX APIs always treat D3DMATRIX and D3DXMATRIX as row-major.”(见d3d9 document/Casting and Conversion 一节)
2)OpenGL 采用列主序存储
“The m parameter points to a 4x4 matrix of single- or double-precision floating-point values stored in column-major order. That is, the matrix is stored as follows”
(见msdn glLoadMatrixf API说明)

存储顺序说明了线性代数中的矩阵如何在线性的内存数组中存储,d3d 将每一行在数组中按行存储,而opengl将每一列存储到数组的每一行中:
      线性代数意义的同一个矩阵,在d3d 和 ogl 中却有不同的存储顺序
              线代:a11,a12,a13,a14               d3d :  a11,a12,a13,a14                   gl: a11,a21,a31,a41
                       a21,a22,a23,a24                         a21,a22,a23,a24                       a12,a22,a32,a42
                       a31,a32,a33,a34                         a31,a32,a33,a34                       a13,a23,a33,a43
                       a41,a42,a43,a44                         a41,a42,a43,a44                       a14,a24,a34,a44

(三)矩阵乘法顺序和规则

矩阵乘法在线性代数中的定义是确定的,然而在不同的实现中出现了“左乘”和“右乘”的区别,或者叫做“前乘(pre-multiply),后乘(post-multiply)”
这个规则取决于vector的表示形式,即行向量还是列向量。如果是行向量,其实就是一个行矩阵。那么表示线性代数意义的“行x列”,就是前乘。矩阵乘法也是如此。
如d3d

                       

D3D 是行向量,行优先存储,OpenGL是列向量,列优先存储。同一个矩阵用D3D存储还是用opengl存储虽然不同,但是变换的结果却是相同,
因为opengl 变换向量是把向量视作列向量,并同矩阵的每一列相乘,用来实现线性代数中同一个变换。

我们通常很难看到opengl变换坐标的代码,以下代码出自opengl source code,让我们一窥顶点变换的“庐山真面目”

void FASTCALL __glXForm3(__GLcoord *res, const __GLfloat v[3], const __GLmatrix *m)
{
    __GLfloat x = v[0];
    __GLfloat y = v[1];
    __GLfloat z = v[2];

    res->x = x*m->matrix[0][0] + y*m->matrix[1][0] + z*m->matrix[2][0]
 + m->matrix[3][0];
    res->y = x*m->matrix[0][1] + y*m->matrix[1][1] + z*m->matrix[2][1]
 + m->matrix[3][1];
    res->z = x*m->matrix[0][2] + y*m->matrix[1][2] + z*m->matrix[2][2]
 + m->matrix[3][2];
    res->w = x*m->matrix[0][3] + y*m->matrix[1][3] + z*m->matrix[2][3]
 + m->matrix[3][3];
}

可见确实如上所述,“OPENGL列向量和矩阵的每一列相乘,仍然表示线性代数行向量和矩阵的每一行相乘”
再来看一下opengl 矩阵相乘,“用a的每一列去乘b的每一行”。

/*
** Compute r = a * b, where r can equal b.
*/
void FASTCALL __glMultMatrix(__GLmatrix *r, const __GLmatrix *a, const __GLmatrix *b)
{
    __GLfloat b00, b01, b02, b03;
    __GLfloat b10, b11, b12, b13;
    __GLfloat b20, b21, b22, b23;
    __GLfloat b30, b31, b32, b33;
    GLint i;

    b00 = b->matrix[0][0]; b01 = b->matrix[0][1];
        b02 = b->matrix[0][2]; b03 = b->matrix[0][3];
    b10 = b->matrix[1][0]; b11 = b->matrix[1][1];
        b12 = b->matrix[1][2]; b13 = b->matrix[1][3];
    b20 = b->matrix[2][0]; b21 = b->matrix[2][1];
        b22 = b->matrix[2][2]; b23 = b->matrix[2][3];
    b30 = b->matrix[3][0]; b31 = b->matrix[3][1];
        b32 = b->matrix[3][2]; b33 = b->matrix[3][3];

    for (i = 0; i < 4; i++) {
 r->matrix[i][0] = a->matrix[i][0]*b00 + a->matrix[i][1]*b10
     + a->matrix[i][2]*b20 + a->matrix[i][3]*b30;
 r->matrix[i][1] = a->matrix[i][0]*b01 + a->matrix[i][1]*b11
     + a->matrix[i][2]*b21 + a->matrix[i][3]*b31;
 r->matrix[i][2] = a->matrix[i][0]*b02 + a->matrix[i][1]*b12
     + a->matrix[i][2]*b22 + a->matrix[i][3]*b32;
 r->matrix[i][3] = a->matrix[i][0]*b03 + a->matrix[i][1]*b13
     + a->matrix[i][2]*b23 + a->matrix[i][3]*b33;

转载于:https://www.cnblogs.com/zengqh/archive/2012/07/09/2583079.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/475076.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 1429. 第一个唯一数字(map+queue)

文章目录1. 题目2. 解题1. 题目 给定一系列整数&#xff0c;插入一个队列中&#xff0c;找出队列中第一个唯一整数。 实现 FirstUnique 类&#xff1a; FirstUnique(int[] nums) 用数组里的数字初始化队列。int showFirstUnique() 返回队列中的 第一个唯一 整数的值。如果没…

LeetCode 1244. 力扣排行榜(map+multiset)

文章目录1. 题目2. 解题1. 题目 新一轮的「力扣杯」编程大赛即将启动&#xff0c;为了动态显示参赛者的得分数据&#xff0c;需要设计一个排行榜 Leaderboard。 请你帮忙来设计这个 Leaderboard 类&#xff0c;使得它有如下 3 个函数&#xff1a; addScore(playerId, score)…

c语言实现ftp网络应用程序,使用C语言socket实现windows pc与ftp服务器通信---socket实现ftp客户端...

code// Client.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include #include #include #pragma comment(lib,"WS2_32.lib")using namespace std;#define PORT 21//FTP端口#define IP_ADDR "x.x.x.x"//主机地址int getPortNum(cha…

LeetCode 562. 矩阵中最长的连续1线段(DP)

文章目录1. 题目2. 解题1. 题目 给定一个01矩阵 M&#xff0c;找到矩阵中最长的连续1线段。 这条线段可以是水平的、垂直的、对角线的或者反对角线的。 示例: 输入: [[0,1,1,0],[0,1,1,0],[0,0,0,1]] 输出: 3 提示: 给定矩阵中的元素数量不会超过 10,000。来源&#xff1a;力…

LeetCode 1151. 最少交换次数来组合所有的 1(滑动窗口)

文章目录1. 题目2. 解题1. 题目 给出一个二进制数组 data&#xff0c;你需要通过交换位置&#xff0c;将数组中 任何位置 上的 1 组合到一起&#xff0c;并返回所有可能中所需 最少的交换次数。 示例 1&#xff1a; 输入&#xff1a;[1,0,1,0,1] 输出&#xff1a;1 解释&#…

LeetCode 742. 二叉树最近的叶节点(建立父节点信息+BFS)

文章目录1. 题目2. 解题1. 题目 给定一个 每个结点的值互不相同 的二叉树&#xff0c;和一个目标值 k&#xff0c;找出树中与目标值 k 最近的叶结点。 这里&#xff0c;与叶结点 最近 表示在二叉树中到达该叶节点需要行进的边数与到达其它叶结点相比最少。 而且&#xff0c;当…

LeetCode 490. 迷宫(BFS/DFS)

文章目录1. 题目2. 解题2.1 BFS2.2 DFS1. 题目 由空地和墙组成的迷宫中有一个球。 球可以向上下左右四个方向滚动&#xff0c;但在遇到墙壁前不会停止滚动。 当球停下时&#xff0c;可以选择下一个方向。 给定球的起始位置&#xff0c;目的地和迷宫&#xff0c;判断球能否在目…

LeetCode 505. 迷宫 II(BFS / Dijkstra 最短路径)

文章目录1. 题目2. 解题2.1 BFS2.2 Dijkstra 最短路径1. 题目 由空地和墙组成的迷宫中有一个球。 球可以向上下左右四个方向滚动&#xff0c;但在遇到墙壁前不会停止滚动。 当球停下时&#xff0c;可以选择下一个方向。 给定球的起始位置&#xff0c;目的地和迷宫&#xff0c…

红米note3android版本,小米-红米note3-LOS-安卓9.0.0-稳定版Stable3.0-来去电归属-农历等-本地化增强适配...

制作者&#xff1a;MOS-Developer基于版本&#xff1a;LineageOS Android最新安卓9.0.0代码适合机型&#xff1a;小米红米note3高配/标配/低配/kenzo注意事项&#xff1a;为了能一直更新和维护&#xff0c;不付费不收费&#xff0c;请把预装的4个软件使用3-5天后再卸载&#xf…

LeetCode 305. 岛屿数量 II(并查集)

文章目录1. 题目2. 解题2.1 超时解2.1 改进计算方法1. 题目 假设你设计一个游戏&#xff0c;用一个 m 行 n 列的 2D 网格来存储你的游戏地图。 起始的时候&#xff0c;每个格子的地形都被默认标记为「水」。 我们可以通过使用 addLand 进行操作&#xff0c;将位置 (row, col)…

LeetCode 265. 粉刷房子 II(DP)

文章目录1. 题目2. 解题1. 题目 假如有一排房子&#xff0c;共 n 个&#xff0c;每个房子可以被粉刷成 k 种颜色中的一种&#xff0c;你需要粉刷所有的房子并且使其相邻的两个房子颜色不能相同。 当然&#xff0c;因为市场上不同颜色油漆的价格不同&#xff0c;所以房子粉刷成…

鸿蒙系统笔记本价格,鸿蒙系统手机华为P50将明年3月发售,华为P40价格骤降至冰点...

原标题&#xff1a;鸿蒙系统手机华为P50将明年3月发售&#xff0c;华为P40价格骤降至冰点鸿蒙系统手机华为P50将明年3月发售&#xff0c;华为P40价格骤降至冰点&#xff01;每一代P系列产品都基于华为研发和业界合作伙伴的最前沿的能力&#xff0c;实现全新的突破&#xff0c;明…

LeetCode 272. 最接近的二叉搜索树值 II(栈+优先队列)

文章目录1. 题目2. 解题1. 题目 给定一个不为空的二叉搜索树和一个目标值 target&#xff0c;请在该二叉搜索树中找到最接近目标值 target 的 k 个值。 注意&#xff1a; 给定的目标值 target 是一个浮点数 你可以默认 k 值永远是有效的&#xff0c;即 k ≤ 总结点数 题目保证…

LeetCode 750. 角矩形的数量(DP)

文章目录1. 题目2. 解题1. 题目 给定一个只包含 0 和 1 的网格&#xff0c;找出其中角矩形的数量。 一个「角矩形」是由四个不同的在网格上的 1 形成的轴对称的矩形。 注意只有4角的位置才需要为 1。并且&#xff0c;4 个 1 需要是不同的。 示例 1&#xff1a; 输入&#xf…

LeetCode 267. 回文排列 II(回溯)

文章目录1. 题目2. 解题1. 题目 给定一个字符串 s &#xff0c;返回其通过重新排列组合后所有可能的回文字符串&#xff0c;并去除重复的组合。 如不能形成任何回文排列时&#xff0c;则返回一个空列表。 示例 1&#xff1a; 输入: "aabb" 输出: ["abba"…

html canvas直线进度条,js+HTML5 canvas 实现简单的加载条(进度条)功能示例

本文实例讲述了jsHTML5 canvas 实现简单的加载条(进度条)功能。分享给大家供大家参考&#xff0c;具体如下&#xff1a;www.jb51.net canvas实现加载条动画/** 获取canvas, canvas本身没有画图能力&#xff0c;相当于一个画布&#xff0c;提供绘制图形的地方* document.getElem…

android 打开移动开关,教你一个让安卓手机运行更流畅的小技巧:打开这个开关即可...

原标题&#xff1a;教你一个让安卓手机运行更流畅的小技巧&#xff1a;打开这个开关即可安卓用户对于“系统优化”这个词一定不会陌生&#xff0c;因为Android系统越用越卡的毛病难以解决&#xff0c;必须进行优化才能保持流畅。那么如何调教才能让爱机达到最快的运行速度呢&am…

matplotlib 绘制梯度下降求解过程

机器学习过程中经常需要可视化&#xff0c;有助于加强对模型和参数的理解。 下面对梯度下降过程进行动图演示&#xff0c;可以修改不同的学习率&#xff0c;观看效果。 import numpy as np import matplotlib.pyplot as plt from IPython import displayX 2*np.random.rand(…

LeetCode 132. 分割回文串 II(DP)

文章目录1. 题目2. 解题1. 题目 给定一个字符串 s&#xff0c;将 s 分割成一些子串&#xff0c;使每个子串都是回文串。 返回符合要求的最少分割次数。 示例: 输入: "aab" 输出: 1 解释: 进行一次分割就可将 s 分割成 ["aa","b"] 这样两个回文…

html无框架,HTML框架技术详例

要将几个.html文件放入一个文件夹//UntitledFrameset-2.html 源码--------------------------------主框架//UntitledFrame-2.html源码------------------------------无标题文档XXXXX系统//UntitledFrame-3.html源码------------------------------无标题文档用户管理用户查询…