Mar*_*ram 5 c++ opengl math matrix
我有以下功能:
void Matrix::Scale(const float xScale, const float yScale, const float zScale)
{
Matrix scaleMatrix;
scaleMatrix.m_data[M11] = xScale;
scaleMatrix.m_data[M22] = yScale;
scaleMatrix.m_data[M33] = zScale;
*this *= scaleMatrix;
}
void Matrix::Translate(const float xTranslation, const float yTranslation, const float zTranslation)
{
Matrix translationMatrix;
translationMatrix.m_data[M14] = xTranslation;
translationMatrix.m_data[M24] = yTranslation;
translationMatrix.m_data[M34] = zTranslation;
*this *= translationMatrix;
}
Run Code Online (Sandbox Code Playgroud)
而且我不确定这两个函数的最后几行.我应该进行预乘法还是后乘法(即我现在正在做的事情).它对这个类的使用有什么影响?我正在使用OpenGL类,所以任何相似之处都可能有用.
编辑:
我的着色器代码如下所示:
void main()
{
gl_Position = vec4(v_xy, 0.0, 1.0) * v_ModelMatrix * v_ViewMatrix * v_ProjectionMatrix;
f_uv = v_uv;
}
Run Code Online (Sandbox Code Playgroud)
我的矩阵乘法函数如下所示:
// Row 1
result[M11] = lhs[M11] * rhs[M11] + lhs[M12] * rhs[M21] + lhs[M13] * rhs[M31] + lhs[M14] * rhs[M41]; // Column 1
result[M12] = lhs[M11] * rhs[M12] + lhs[M12] * rhs[M22] + lhs[M13] * rhs[M32] + lhs[M14] * rhs[M42]; // Column 2
result[M13] = lhs[M11] * rhs[M13] + lhs[M12] * rhs[M23] + lhs[M13] * rhs[M33] + lhs[M14] * rhs[M43]; // Column 3
result[M14] = lhs[M11] * rhs[M14] + lhs[M12] * rhs[M24] + lhs[M13] * rhs[M34] + lhs[M14] * rhs[M44]; // Column 4
// Row 2
result[M21] = lhs[M21] * rhs[M11] + lhs[M22] * rhs[M21] + lhs[M23] * rhs[M31] + lhs[M24] * rhs[M41]; // Column 1
result[M22] = lhs[M21] * rhs[M12] + lhs[M22] * rhs[M22] + lhs[M23] * rhs[M32] + lhs[M24] * rhs[M42]; // Column 2
result[M23] = lhs[M21] * rhs[M13] + lhs[M22] * rhs[M23] + lhs[M23] * rhs[M33] + lhs[M24] * rhs[M43]; // Column 3
result[M24] = lhs[M21] * rhs[M14] + lhs[M22] * rhs[M24] + lhs[M23] * rhs[M34] + lhs[M24] * rhs[M44]; // Column 4
// Row 3
result[M31] = lhs[M31] * rhs[M11] + lhs[M32] * rhs[M21] + lhs[M33] * rhs[M31] + lhs[M34] * rhs[M41]; // Column 1
result[M32] = lhs[M31] * rhs[M12] + lhs[M32] * rhs[M22] + lhs[M33] * rhs[M32] + lhs[M34] * rhs[M42]; // Column 2
result[M33] = lhs[M31] * rhs[M13] + lhs[M32] * rhs[M23] + lhs[M33] * rhs[M33] + lhs[M34] * rhs[M43]; // Column 3
result[M34] = lhs[M31] * rhs[M14] + lhs[M32] * rhs[M24] + lhs[M33] * rhs[M34] + lhs[M34] * rhs[M44]; // Column 4
// Row 4
result[M41] = lhs[M41] * rhs[M11] + lhs[M42] * rhs[M21] + lhs[M43] * rhs[M31] + lhs[M44] * rhs[M41]; // Column 1
result[M42] = lhs[M41] * rhs[M12] + lhs[M42] * rhs[M22] + lhs[M43] * rhs[M32] + lhs[M44] * rhs[M42]; // Column 2
result[M43] = lhs[M41] * rhs[M13] + lhs[M42] * rhs[M23] + lhs[M43] * rhs[M33] + lhs[M44] * rhs[M43]; // Column 3
result[M44] = lhs[M41] * rhs[M14] + lhs[M42] * rhs[M24] + lhs[M43] * rhs[M34] + lhs[M44] * rhs[M44]; // Column 4
Run Code Online (Sandbox Code Playgroud)
我的印象是,如果你对你的矩阵进行后乘(即viewMatrix = transform * viewMatrix;),那么你的着色器代码需要按照我现在的相反顺序应用MVP?
EDIT2:
http://scratchapixel.com/lessons/3d-basic-lessons/lesson-4-geometry/conventions-again-row-major-vs-column-major-vector/上的汇总表让我感到困惑,因为我是使用OpenGL后复制(指示列主要),但我的矩阵在内存中布局为行主要?
use*_*490 18
你似乎在这里混合了两个问题,我猜想刮擦像素上的网页试图解释什么.从您所指的页面上的信息来看,事情看起来非常清楚但是在脑海中获得这种类型的东西很难.你有这个理论(你用数学和纸笔做什么)以及你用你的实现做什么(C++).这是两个不同的问题.
数学:你可以使用两种符号,无论是列还是行.由于本网页提及GraphicsMuncher以及与行的主要载体,在纸面上,你需要写向量矩阵乘法VM,其中v为行向量(1×4)和M你的4x4矩阵,为什么,因为你可以用数学只写[1x4]*[4x4],而不是相反.类似地,如果使用列,则需要垂直向下写入向量,或者用符号[4x1](4行,1列)向下写入向量.因此,与矩阵的乘法只能写成:[4x4] [4x1].矩阵放在向量的前面:Mv.第一种表示法称为后乘法,第二种称谓法(Mv)称为预乘法(矩阵在前面).现在,正如GraphicsMuncher所提到的,如果你需要变换一个向量(或一个点),那么当你把它们写下来时,你需要注意乘法的顺序.如果你想用矩阵T翻译某些东西,然后用R旋转然后用S缩放,那么在一个专栏主要世界中,你需要写一个v'= S*R*T*v.你需要一个主要的世界写v'= v*T*R*S.
那就是理论.
计算机:当你决定用C++实现这一点时,就说明了这一点.关于这一点的好处是C++不会强加任何关于任何事情的东西.您可以按照您希望的方式在矩阵中映射矩阵系数的值,您可以编写代码,以您希望的方式执行另一个矩阵的矩阵乘法.类似地,如何访问向量矩阵乘法的系数完全取决于您.
您需要明确区分如何在内存中映射系数,以及从视图的数学点使用哪些约定来表示向量.这是两个独立的问题.例如,在您的情况下,您可能将矩阵类声明为16个连续浮点数组.没关系.凡系数M14,M24,M34代表矩阵(TX,泰,Tz的)翻译部分,所以你认为你的"公约"是行优先,即使你被告知使用OpenGL矩阵的公约被认为是列 - 重大的.在这里,你的困惑来自这样一个事实,即内存中系数的映射与你自己构成"列主要"矩阵的心理表示不同.你编码"行",但据说你使用(从数学的角度来看)"列",因此很难理解你是做对还是错.
重要的是将矩阵看作由三个轴定义的坐标系的表示和平移.将此数据存储在内存中的位置和方式完全取决于您.假设表示坐标系的三个轴的三个向量被命名为AX(x,y,z),AY(x,y,z),AZ(x,y,z),并且平移向量由(Tx)表示,Ty,Tz),然后在数学上如果你使用列矢量(我猜不到乳胶):
AXx AYx AZx Tx
M = AXy AYy AZy Ty
AXz AYz AZz Tz
0 0 0 1
Run Code Online (Sandbox Code Playgroud)
坐标系的轴垂直写入.现在,如果你使用row-major:
AXx AXy AXz 0
M = AYx AYy AYz 0
AZx AZy AZz 0
Tx Ty Tz 1
Run Code Online (Sandbox Code Playgroud)
坐标系的轴是水平写入的.因此,现在涉及计算机世界的问题是如何将这些系数存储在内存中.你也可以这样做:
float m[16] = { AXx, AXy, AXz, 0, AYx, AYy, AYz, 0, AZx, AZy, AZz, 0, Tx, Ty, Tz, 1};
Run Code Online (Sandbox Code Playgroud)
它会告诉你你使用哪种约定?不,你也可以这样写:
float m[16] = { AXx, AXy, AXz, Tx, AYx, AYy, AYz, Ty, AZx, AZy, AZz, Tz, 0, 0, 0, 1};
Run Code Online (Sandbox Code Playgroud)
要么
float m[16] = { AXx, AYx, AZx, Tx, AXy, AYy, AZy, Ty, AXz, AYz, AZz, Tz, 0, 0, 0, 1};
Run Code Online (Sandbox Code Playgroud)
再次,这并没有给出您使用哪种"数学"惯例的特定指示.您只是以不同的方式在内存中存储16个系数,只要您知道这种方式是什么就完全没问题,以便您以后可以适当地访问它们.现在请记住,无论使用行 - 列 - 数学符号,向量乘以矩阵都应该为您提供相同的向量.因此,重要的是你将矢量的(x,y,z)坐标乘以矩阵中的右系数,这需要知道"你"如何决定将矩阵系数存储在内存中:
Vector3 vecMatMult (Vector3 v,
float AXx, float AXy, float AXz, float Tx,
float AYx, float AYy, float AYz, float Ty,
float AZz, float AZy, float AZz, float Tz) {
return Vector3(
v.x * AXx + v.y * AYx + v.z * AZx + Tx,
v.x * AXy + v.y * AYy + v.z * AZy + Ty,
v.x * AXz + v.y * AYz + v.z * AZz + Tz
}
Run Code Online (Sandbox Code Playgroud)
编辑:上面的代码是错误的,现在修复它.
我写了这个功能,强调一个事实,即您使用无论哪个惯例,矢量所得到的*矩阵乘法仅仅是一个乘法和坐标中的向量的输入之间的加法和坐标系的轴坐标AX,AY和AZ(不管您使用的符号,无论您将它们存储在内存中的方式如何).
如果您使用:
float m[16] = { AXx, AXy, AXz, 0, AYx, AYy, AYz, 0, AZx, AZy, AZz, 0, Tx, Ty, Tz, 1};
Run Code Online (Sandbox Code Playgroud)
你需要打电话:
vecMatMult(v, m[0], m[1], m[2], m[12], m[4], m[5], m[6], m[13], ...
Run Code Online (Sandbox Code Playgroud)
如果您使用:
float m[16] = { AXx, AYx, AZx, Tx, AXy, AYy, AZy, Ty, AXz, AYz, AZz, Tz, 0, 0, 0, 1};
Run Code Online (Sandbox Code Playgroud)
你需要打电话:
vecMatMult(v, m[0], m[4], m[8], m[3], m[1], m[5], m[9], m[10], ...
Run Code Online (Sandbox Code Playgroud)
这会告诉你使用哪种约定?不.当你进行vec*mat乘法时,你只需要在正确的位置调用正确的系数.这就是它的全部内容,尽管看似令人不安.
现在,在mat*mat乘法方面,情况略有不同.您可以假设矩阵乘以的顺序不一样.所以R*S*T与T*S*R不同.顺序确实很重要.现在再次如果你使用"行专业",那么在数学上你需要写(使用你的符号):
mt11 = ml11*mr11 + ml12*mr21 + m13*m31 + ml14*mr41
其中ml是左手矩阵,右手是mr:mt = ml*mr.但请注意,我没有使用方括号[]作为访问索引,因为我不想建议我们访问存储在一维数组中的元素.我们只是在讨论矩阵的系数.如果你想用C++编写,那么一切都取决于你如何将系数存储在内存中,如上所述.
希望能帮助到你.