zoukankan      html  css  js  c++  java
  • 各大引擎矩阵的矩阵存储方式 ----行矩阵 or 列矩阵

    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+16]    // M[1][0]
    movups    xmm6,[ecx+32]    // M[2][0]
    movups    xmm7,[ecx+48]    // M[3][0]
    
    movss    xmm0,[eax]FVector.X
    shufps    xmm0,xmm0,0
    mulps    xmm0,xmm4
    
    movss    xmm1,[eax]FVector.Y
    shufps    xmm1,xmm1,0
    mulps    xmm1,xmm5
    
    movss    xmm2,[eax]FVector.Z
    shufps    xmm2,xmm2,0
    mulps    xmm2,xmm6
    
    addps    xmm0,xmm1
    
    movss    xmm3,[eax]FVector4.W
    shufps    xmm3,xmm3,0
    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[0][0] + P.Y * M[1][0] + P.Z * M[2][0] + P.W * M[3][0];
    Result.Y = P.X * M[0][1] + P.Y * M[1][1] + P.Z * M[2][1] + P.W * M[3][1];
    Result.Z = P.X * M[0][2] + P.Y * M[1][2] + P.Z * M[2][2] + P.W * M[3][2];
    Result.W = P.X * M[0][3] + P.Y * M[1][3] + P.Z * M[2][3] + P.W * M[3][3];
    #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 是列矩阵

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

      

  • 相关阅读:
    阿里云短信服务工具类
    vue.config.js
    elementui Tree 树形控件增删改查
    vue 实时显示年月日时分秒星期上下午
    1553:【例 2】暗的连锁
    CF825G Tree Queries
    最短母串
    寻找好串
    无限链计数
    异或运算
  • 原文地址:https://www.cnblogs.com/dragon2012/p/5147382.html
Copyright © 2011-2022 走看看