OpenGL  里面的矩阵

float  m[16];

OpenGL中的矩阵是这样的
m[0]  m[4]  m[8]    m[12]
m[1] m[5] m[9] m[13]
m[2] m[6] m[10] m[14]
m[3] m[7] m[11] m[15]

  

对它定义的新坐标系,OpenGL是这么说的:
x轴向量(m[0], m[1], m[2]);
y轴向量(m[4], m[5], m[6]);
z轴向量(m[8], m9], m[10]);
原点(m[12], m[13], m[14]);

  


乘法是这样的
x'  = m[0]x   + m[4]y   +m[8]z   + m[12]w;
y' = m[1]x + m[5]y +m[9]z + m[13]w;
z' = m[2]x + m[6]y +m[10]z + m[14]w;
w' = m[3]x + m[7]y +m[11]z + m[15]w;

  

分割线  补充

id 的idmat4

//===============================================================
//
// idMat4 - 4x4 matrix
//
//=============================================================== class idMat4 {
public:
idMat4( void );
explicit idMat4( const idVec4 &x, const idVec4 &y, const idVec4 &z, const idVec4 &w );
explicit idMat4(const float xx, const float xy, const float xz, const float xw,
const float yx, const float yy, const float yz, const float yw,
const float zx, const float zy, const float zz, const float zw,
const float wx, const float wy, const float wz, const float ww );
explicit idMat4( const idMat3 &rotation, const idVec3 &translation );
explicit idMat4( const float src[ 4 ][ 4 ] ); const idVec4 & operator[]( int index ) const;
idVec4 & operator[]( int index );
idMat4 operator*( const float a ) const;
idVec4 operator*( const idVec4 &vec ) const;
idVec3 operator*( const idVec3 &vec ) const;
idMat4 operator*( const idMat4 &a ) const;
idMat4 operator+( const idMat4 &a ) const;
idMat4 operator-( const idMat4 &a ) const;
idMat4 & operator*=( const float a );
idMat4 & operator*=( const idMat4 &a );
idMat4 & operator+=( const idMat4 &a );
idMat4 & operator-=( const idMat4 &a ); friend idMat4 operator*( const float a, const idMat4 &mat );
friend idVec4 operator*( const idVec4 &vec, const idMat4 &mat );
friend idVec3 operator*( const idVec3 &vec, const idMat4 &mat );
friend idVec4 & operator*=( idVec4 &vec, const idMat4 &mat );
friend idVec3 & operator*=( idVec3 &vec, const idMat4 &mat ); bool Compare( const idMat4 &a ) const; // exact compare, no epsilon
bool Compare( const idMat4 &a, const float epsilon ) const; // compare with epsilon
bool operator==( const idMat4 &a ) const; // exact compare, no epsilon
bool operator!=( const idMat4 &a ) const; // exact compare, no epsilon void Zero( void );
void Identity( void );
bool IsIdentity( const float epsilon = MATRIX_EPSILON ) const;
bool IsSymmetric( const float epsilon = MATRIX_EPSILON ) const;
bool IsDiagonal( const float epsilon = MATRIX_EPSILON ) const;
bool IsRotated( void ) const; void ProjectVector( const idVec4 &src, idVec4 &dst ) const;
void UnprojectVector( const idVec4 &src, idVec4 &dst ) const; float Trace( void ) const;
float Determinant( void ) const;
idMat4 Transpose( void ) const; // returns transpose
idMat4 & TransposeSelf( void );
idMat4 Inverse( void ) const; // returns the inverse ( m * m.Inverse() = identity )
bool InverseSelf( void ); // returns false if determinant is zero
idMat4 InverseFast( void ) const; // returns the inverse ( m * m.Inverse() = identity )
bool InverseFastSelf( void ); // returns false if determinant is zero
idMat4 TransposeMultiply( const idMat4 &b ) const; int GetDimension( void ) const; const float * ToFloatPtr( void ) const;
float * ToFloatPtr( void );
const char * ToString( int precision = 2 ) const; private:
idVec4 mat[ 4 ];
}; ID_INLINE idVec4 idMat4::operator*( const idVec4 &vec ) const {
return idVec4(
mat[ 0 ].x * vec.x + mat[ 0 ].y * vec.y + mat[ 0 ].z * vec.z + mat[ 0 ].w * vec.w,
mat[ 1 ].x * vec.x + mat[ 1 ].y * vec.y + mat[ 1 ].z * vec.z + mat[ 1 ].w * vec.w,
mat[ 2 ].x * vec.x + mat[ 2 ].y * vec.y + mat[ 2 ].z * vec.z + mat[ 2 ].w * vec.w,
mat[ 3 ].x * vec.x + mat[ 3 ].y * vec.y + mat[ 3 ].z * vec.z + mat[ 3 ].w * vec.w );
} ID_INLINE idVec3 idMat4::operator*( const idVec3 &vec ) const {
float s = mat[ 3 ].x * vec.x + mat[ 3 ].y * vec.y + mat[ 3 ].z * vec.z + mat[ 3 ].w;
if ( s == 0.0f ) {
return idVec3( 0.0f, 0.0f, 0.0f );
}
if ( s == 1.0f ) {
return idVec3(
mat[ 0 ].x * vec.x + mat[ 0 ].y * vec.y + mat[ 0 ].z * vec.z + mat[ 0 ].w,
mat[ 1 ].x * vec.x + mat[ 1 ].y * vec.y + mat[ 1 ].z * vec.z + mat[ 1 ].w,
mat[ 2 ].x * vec.x + mat[ 2 ].y * vec.y + mat[ 2 ].z * vec.z + mat[ 2 ].w );
}
else {
float invS = 1.0f / s;
return idVec3(
(mat[ 0 ].x * vec.x + mat[ 0 ].y * vec.y + mat[ 0 ].z * vec.z + mat[ 0 ].w) * invS,
(mat[ 1 ].x * vec.x + mat[ 1 ].y * vec.y + mat[ 1 ].z * vec.z + mat[ 1 ].w) * invS,
(mat[ 2 ].x * vec.x + mat[ 2 ].y * vec.y + mat[ 2 ].z * vec.z + mat[ 2 ].w) * invS );
}    
  

  idsoft的并不完全是OpenGL的矩阵相匹配,他是行矩阵

Ogre的

/** \addtogroup Math
* @{
*/
/** Class encapsulating a standard 4x4 homogeneous matrix.
@remarks
OGRE uses column vectors when applying matrix multiplications,
This means a vector is represented as a single column, 4-row
matrix. This has the effect that the transformations implemented
by the matrices happens right-to-left e.g. if vector V is to be
transformed by M1 then M2 then M3, the calculation would be
M3 * M2 * M1 * V. The order that matrices are concatenated is
vital since matrix multiplication is not commutative, i.e. you
can get a different result if you concatenate in the wrong order.
@par
The use of column vectors and right-to-left ordering is the
standard in most mathematical texts, and is the same as used in
OpenGL. It is, however, the opposite of Direct3D, which has
inexplicably chosen to differ from the accepted standard and uses
row vectors and left-to-right matrix multiplication.
@par
OGRE deals with the differences between D3D and OpenGL etc.
internally when operating through different render systems. OGRE
users only need to conform to standard maths conventions, i.e.
right-to-left matrix multiplication, (OGRE transposes matrices it
passes to D3D to compensate).
@par
The generic form M * V which shows the layout of the matrix
entries is shown below:
<pre>
[ m[0][0] m[0][1] m[0][2] m[0][3] ] {x}
| m[1][0] m[1][1] m[1][2] m[1][3] | * {y}
| m[2][0] m[2][1] m[2][2] m[2][3] | {z}
[ m[3][0] m[3][1] m[3][2] m[3][3] ] {1}
</pre>
*/
class _OgreExport Matrix4
{
protected:
/// The matrix entries, indexed by [row][col].
union {
Real m[4][4];
Real _m[16];
};
public: inline Vector4 operator * (const Vector4& v) const
{
return Vector4(
m[0][0] * v.x + m[0][1] * v.y + m[0][2] * v.z + m[0][3] * v.w,
m[1][0] * v.x + m[1][1] * v.y + m[1][2] * v.z + m[1][3] * v.w,
m[2][0] * v.x + m[2][1] * v.y + m[2][2] * v.z + m[2][3] * v.w,
m[3][0] * v.x + m[3][1] * v.y + m[3][2] * v.z + m[3][3] * v.w
);
}
};

  Ogre也是一样,行矩阵

NVIDIA 的

template<class T>
class matrix4
{ public:
// dst = M * src
vec4<T> operator *( const vec4<T> &src) const
{
vec4<T> r;
for ( int32_t i = 0; i < 4; i++)
r[i] = ( src[0] * element(i,0) + src[1] * element(i,1) +
src[2] * element(i,2) + src[3] * element(i,3));
return r;
}   
T & element (int32_t row, int32_t col)
{
return _array[row | (col<<2)];
} const T & element (int32_t row, int32_t col) const
{
return _array[row | (col<<2)];
} union
{
struct
{
T _11, _12, _13, _14; // standard names for components
T _21, _22, _23, _24; // standard names for components
T _31, _32, _33, _34; // standard names for components
T _41, _42, _43, _44; // standard names for components
};
T _array[16]; // array access
};
};

这里我翻译下

vec4<T> operator *( const vec4<T> &src) const 

{
  vec4<T> ret;
ret[0] = _array[0] * src[0] + _array[4]* src[1] + _array[8] *src[2] + _array[12] *src[3];
ret[1] = _array[1] * src[0] + _array[5]* src[1] + _array[9] *src[2] + _array[13] *src[3];
ret[2] = _array[2] * src[0] + _array[6]* src[1] + _array[10] *src[2] + _array[14] *src[3];
ret[3] = _array[3] * src[0] + _array[7]* src[1] + _array[11] *src[2] + _array[15] *src[3]; return ret;
}

 所以和OpenGL一模一样 ,列矩阵

 

gkEngine

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// struct Matrix44_tpl
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
template<typename F, class A=XMVec4A> struct Matrix44_tpl
{
#ifndef XENON_INTRINSICS
F m00,m01,m02,m03;
F m10,m11,m12,m13;
F m20,m21,m22,m23;
F m30,m31,m32,m33; //! transform a vector
Vec3 TransformVector(const Vec3 &b) const {
assert(b.IsValid());
Vec3 v;
v.x = m00*b.x + m01*b.y + m02*b.z;
v.y = m10*b.x + m11*b.y + m12*b.z;
v.z = m20*b.x + m21*b.y + m22*b.z;
return v;
}
//! transform a point
Vec3 TransformPoint(const Vec3 &b) const {
assert(b.IsValid());
Vec3 v;
v.x = m00*b.x + m01*b.y + m02* b.z + m03;
v.y = m10*b.x + m11*b.y + m12* b.z + m13;
v.z = m20*b.x + m21*b.y + m22* b.z + m23;
return v;
}
};

他是行矩阵  

 

再来一个gameplay的

/**
* Defines a 4 x 4 floating point matrix representing a 3D transformation.
*
* Vectors are treated as columns, resulting in a matrix that is represented as follows,
* where x, y and z are the translation components of the matrix:
*
* 1 0 0 x
* 0 1 0 y
* 0 0 1 z
* 0 0 0 1
*
* This matrix class is directly compatible with OpenGL since its elements are
* laid out in memory exactly as they are expected by OpenGL.
* The matrix uses column-major format such that array indices increase down column first.
* Since matrix multiplication is not commutative, multiplication must be done in the
* correct order when combining transformations. Suppose we have a translation
* matrix T and a rotation matrix R. To first rotate an object around the origin
* and then translate it, you would multiply the two matrices as TR.
*
* Likewise, to first translate the object and then rotate it, you would do RT.
* So generally, matrices must be multiplied in the reverse order in which you
* want the transformations to take place (this also applies to
* the scale, rotate, and translate methods below; these methods are convenience
* methods for post-multiplying by a matrix representing a scale, rotation, or translation).
*
* In the case of repeated local transformations (i.e. rotate around the Z-axis by 0.76 radians,
* then translate by 2.1 along the X-axis, then ...), it is better to use the Transform class
* (which is optimized for that kind of usage).
*
* @see Transform
*/
class Matrix
{
public: /**
* Stores the columns of this 4x4 matrix.
* */
float m[16];
} inline void MathUtil::transformVector4(const float* m, float x, float y, float z, float w, float* dst)
{
dst[0] = x * m[0] + y * m[4] + z * m[8] + w * m[12];
dst[1] = x * m[1] + y * m[5] + z * m[9] + w * m[13];
dst[2] = x * m[2] + y * m[6] + z * m[10] + w * m[14];
} inline void MathUtil::transformVector4(const float* m, const float* v, float* dst)
{
// Handle case where v == dst.
float x = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + v[3] * m[12];
float y = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + v[3] * m[13];
float z = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + v[3] * m[14];
float w = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + v[3] * m[15]; dst[0] = x;
dst[1] = y;
dst[2] = z;
dst[3] = w;
}

当然这个说明里已经写了是Opengl的了,那么自然是列矩阵。

等回家看看cryEngine 和 sourceEngine的

----------------------------------我是分割线------------------------------------------------

cryEngine的

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// struct Matrix44_tpl
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
template<typename F, class A=XMVec4A> struct Matrix44_tpl
{
#ifndef XENON_INTRINSICS
F m00,m01,m02,m03;
F m10,m11,m12,m13;
F m20,m21,m22,m23;
F m30,m31,m32,m33; }; template<class F1, class F2, class B>
ILINE Vec4_tpl<F1> operator*(const Matrix44_tpl<F2, B> &m, const Vec4_tpl<F1> &v)
{
CHECK_SIMD_ALIGNMENT_P(&v);
assert(m.IsValid());
assert(v.IsValid());
return Vec4_tpl<F1>(v.x*m.m00 + v.y*m.m01 + v.z*m.m02 + v.w*m.m03,
v.x*m.m10 + v.y*m.m11 + v.z*m.m12 + v.w*m.m13,
v.x*m.m20 + v.y*m.m21 + v.z*m.m22 + v.w*m.m23,
v.x*m.m30 + v.y*m.m31 + v.z*m.m32 + v.w*m.m33);
}

可见CryEngine是行矩阵,CryEngine只有Dx的渲染方式,不可能用Opengl的列矩阵吧,呵呵

下面是SourceEngine

//=============================================================================//
//
// VMatrix always postmultiply vectors as in Ax = b.
// Given a set of basis vectors ((F)orward, (L)eft, (U)p), and a (T)ranslation,
// a matrix to transform a vector into that space looks like this:
// Fx Lx Ux Tx
// Fy Ly Uy Ty
// Fz Lz Uz Tz
// 0 0 0 1 // Note that concatenating matrices needs to multiply them in reverse order.
// ie: if I want to apply matrix A, B, then C, the equation needs to look like this:
// C * B * A * v
// ie:
// v = A * v;
// v = B * v;
// v = C * v; class VMatrix
{
public:
// The matrix.
vec_t m[4][4];
}; inline Vector VMatrix::operator*(const Vector &vVec) const
{
Vector vRet;
vRet.x = m[0][0]*vVec.x + m[0][1]*vVec.y + m[0][2]*vVec.z + m[0][3];
vRet.y = m[1][0]*vVec.x + m[1][1]*vVec.y + m[1][2]*vVec.z + m[1][3];
vRet.z = m[2][0]*vVec.x + m[2][1]*vVec.y + m[2][2]*vVec.z + m[2][3]; return vRet;
} inline Vector VMatrix::VMul3x3(const Vector &vVec) const
{
return Vector(
m[0][0]*vVec.x + m[0][1]*vVec.y + m[0][2]*vVec.z,
m[1][0]*vVec.x + m[1][1]*vVec.y + m[1][2]*vVec.z,
m[2][0]*vVec.x + m[2][1]*vVec.y + m[2][2]*vVec.z
);
}

SourceEngine也不是列矩阵,而是行矩阵

2016 -6 -17 添加 unreal3

// Homogeneous transform.

FORCEINLINE FVector4 FMatrix::TransformFVector4(const FVector4 &P) const
{
FVector4 Result; #if ASM_X86
#ifdef _MSC_VER
__asm
{
mov eax,[P]
mov ecx,[this] movups xmm4,[ecx] // M[0][0]
movups xmm5,[ecx+] // M[1][0]
movups xmm6,[ecx+] // M[2][0]
movups xmm7,[ecx+] // M[3][0] movss xmm0,[eax]FVector.X
shufps xmm0,xmm0,
mulps xmm0,xmm4 movss xmm1,[eax]FVector.Y
shufps xmm1,xmm1,
mulps xmm1,xmm5 movss xmm2,[eax]FVector.Z
shufps xmm2,xmm2,
mulps xmm2,xmm6 addps xmm0,xmm1 movss xmm3,[eax]FVector4.W
shufps xmm3,xmm3,
mulps xmm3,xmm7 // stall
lea eax,[Result] addps xmm2,xmm3 // stall addps xmm0,xmm2 movups [eax],xmm0
}
#else
#error Please implement for your compiler.
#endif #else
Result.X = P.X * M[][] + P.Y * M[][] + P.Z * M[][] + P.W * M[][];
Result.Y = P.X * M[][] + P.Y * M[][] + P.Z * M[][] + P.W * M[][];
Result.Z = P.X * M[][] + P.Y * M[][] + P.Z * M[][] + P.W * M[][];
Result.W = P.X * M[][] + P.Y * M[][] + P.Z * M[][] + P.W * M[][];
#endif return Result;
} // Regular transform. /** Transform a location - will take into account translation part of the FMatrix. */
FORCEINLINE FVector4 FMatrix::TransformFVector(const FVector &V) const
{
return TransformFVector4(FVector4(V.X,V.Y,V.Z,1.0f));
}

unreal 是列矩阵

大部分都是按照个人的习惯吧

  

各大引擎矩阵的矩阵存储方式 ----行矩阵 or 列矩阵的更多相关文章

  1. 纠结和郁闷的存在感-关于DirectX与HLSL的矩阵存储方式---转载好文章

    我常常这么大胆的认为,搞科学的人总是喜欢用各种让常人难以理解的复杂方式去处理某些其实可能很简单的事情,这种情况在他自身擅长的.有着诸多对手竞争的领域上极为常见.比如吧,搞DirectX的人用了左手坐标 ...

  2. unity3d的矩阵元素存储方式

    想知道u3d矩阵各个元素的存储方式,所以测试了一下 Matrix4x4 m = Matrix4x4.TRS(new Vector3(1, 2, 3), Quaternion.Euler(0, 0, 3 ...

  3. 特殊矩阵的压缩存储(转自chunlanse2014)

    对称矩阵 对于一个矩阵结构显然用一个二维数组来表示是非常恰当的,但在有些情况下,比如常见的一些特殊矩阵,如三角矩阵.对称矩阵.带状矩阵.稀疏矩阵等,从节约存储空间的角度考虑,这种存储是不太合适的.下面 ...

  4. C++ 特殊矩阵的压缩存储算法

    1. 前言 什么是特殊矩阵? C++,一般使用二维数组存储矩阵数据. 在实际存储时,会发现矩阵中有许多值相同的数据或有许多零数据,且分布呈现出一定的规律,称这类型的矩阵为特殊矩阵. 为了节省存储空间, ...

  5. C语言判断系统数据大/小端存储方式

    小端存储:数据的低位部分,存储于存储器的低地址空间里. 大端存储:数据的低位部分,存储于存储器的高地址空间里. 首先,一般PC数据存储方式是小端存储. 基本实现思想是:将存储器中所存的数据按字节以地址 ...

  6. MongoDB wiredTiger存储引擎下的存储方式LSM和B-Tree比较

    前段时间做拦截件监控的时候把拦截件生命期存入mongodb,因生命期有各种变化,因此对此表的更新写操作非常多,老大给我看了一篇文章,才知道mongodb已经支持lsm存储方式了. 原文如连接:http ...

  7. 【HTML5】296- 重新复习 HTML5 的 5大存储方式

    点击上方"前端自习课"关注,学习起来~ 一.介绍 在 HTML5 规范之前,存储主要是用 cookies . cookies 的缺点有: 在请求头上带着数据: 大小是 4k 之内: ...

  8. Matlab中数据的存储方式

    简介 MATLAB提供了丰富的算法以及一个易于操作的语言,给算法研发工作者提供了很多便利.然而MATLAB在执行某些任务的时候,执行效率偏低,测试较大任务量时可能会引起较长时间的等待.未解决这个问题, ...

  9. .NET C#教程初级篇 1-1 基本数据类型及其存储方式

    .NET C# 教程初级篇 1-1 基本数据类型及其存储方式 全文目录 (博客园).NET Core Guide (Github).NET Core Guide 本节内容是对于C#基础类型的存储方式以 ...

随机推荐

  1. Python获取间隔时间段的时间戳数据

    import time import datetime today = datetime.datetime.now() # delta = datetime.timedelta(hours=1) de ...

  2. css样式实现左边的固定宽度和高度的图片或者div跟随右边高度不固定的文字或者div垂直居中(文字高度超过图片,图片跟随文字居中,反之文字跟随图片居中非table实现)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. 在构造函数中使用new时的注意事项

    果然,光看书是没用的,一编程序,很多问题就出现了-- 注意事项: 1. 如果构造函数中适用了new初始化指针成员,则构析函数中必须要用delete 2. new与delete必须兼容,new对应del ...

  4. ZooKeeper管理分布式环境中的数据

    Reference: http://www.cnblogs.com/wuxl360/p/5817549.html 本节本来是要介绍ZooKeeper的实现原理,但是ZooKeeper的原理比较复杂,它 ...

  5. Oracle Database 11g Release 2 Standard Edition and Enterprise Edition Software Downloads

    Oracle Database 11g Release 2 Standard Edition and Enterprise Edition Software DownloadsOracle 数据库 1 ...

  6. 机器学习集成算法--- 朴素贝叶斯,k-近邻算法,决策树,支持向量机(SVM),Logistic回归

    朴素贝叶斯: 是使用概率论来分类的算法.其中朴素:各特征条件独立:贝叶斯:根据贝叶斯定理.这里,只要分别估计出,特征 Χi 在每一类的条件概率就可以了.类别 y 的先验概率可以通过训练集算出 k-近邻 ...

  7. 使用xcode 7 开发cocos2dx问题

    使用xcode 7 开发cocos2dx问题 近期在学习cocos2dx使用xcode 7 bate 最为开发工具,由于xcode 7 能够不用增加开发人员就能真机測试啦,哈哈.可是当我创建好coco ...

  8. VBA中数据库导出数据到Excel注意事项

    Sub ReadDBData() On Error GoTo ErrorHand Dim dbHelper As New dbHelper Dim sqlSQL As String Dim rs As ...

  9. sql 字符带下划线匹配问题

    SQL 中 _下划线 作用是 匹配一个任意字符. 如果我们要去掉下划线的作用 单纯只用作一个字符则需要转义成    like '%\_%' escape '\' 字段 1.order_qrsc 2.o ...

  10. python里面有人写while 循环用 用while 1 和while True的区别

    由于Python2中,True/False不是关键字,因此我们可以对其进行任意的赋值,这就导致程序在每次循环时都需要对True/False的值进行检查:而对于1,则被程序进行了优化,而后不会再进行检查 ...