행벡터는 행이 축 Part2

2007/12/15 20:36
최근에 어째서 행벡터에서 열이 축인가 헷갈렸는지 알게되었다.

툴에서 카메라를 이동시키는 코드가 있었는데, 이 코드는 카메라를 x축 상으로 움직일때 (LookAt으로 만들어지는)View Matrix에서 _11, _21, _31을 가져왔었다. 그걸보고 햇병아리때 '오, 축은 열인갑다'라고 생각했었고 그게 머리속에 각인되어서 쭉 행벡터의 열이 축인줄 알았나 보다.

View Matrix는 좌표계 변환의 일종이고, 좌표계 변환은 Affine 변환의 일종이며, Affine변환에서 축들의 평행성은 유지되고 역은 전치된다. 그래서 카메라 좌표계의 _11, _12, _13이 전치되어 있는 View Matrix에서 _11, _21, _31을 가져오는 것이다.

행벡터는 행이 축이라는것을 실제적으로 보여주는 간단한 예가 있다.
                                 ( a11, a12, a13
(x', y', z') = (1,0,0) *    a21, a22, a23
                                   a31, a32, a33 )
기존의 x축의 기저를 어떤 Affine 변환을 해서 새로운 축 x', y', z'를 얻었다고 하자.
계산을 해보면,
(x', y', z') = ( 1*a11 + 0*a21 + 0*a31, 1*a12 + 0*a22 + 0*a32, 1*a13 + 0*a23 + 0*a33)
(x', y', z') = (a11, a12, a13)
이 되어 행벡터는 행이 축이라는것을 계산적으로 보여준다.

수학 이야기 선형대수, 행렬

익명 공용체와 익명 구조체 ( anonymous union / anonymous structure )

2007/08/19 22:57
익명의 공용체에 익명 구조체를 쓰는것은 대부분의 C++ 컴파일러가 지원하는 확장이지만 표준은 아니다.
꼴에 표준을 좋아해서 DX에서 쓰이는 아래의 행렬은 새로 작성하고 있는 end 의 행렬객체로는 부적격.

(Language : cpp)
typedef struct _D3DMATRIX {
    union {
        struct {
            float        _11, _12, _13, _14;
            float        _21, _22, _23, _24;
            float        _31, _32, _33, _34;
            float        _41, _42, _43, _44;

        };
        float m[4][4];
    };
} D3DMATRIX;


현재는 이런식으로 행렬 클래스를 설계하고 있다.

(Language : cpp)
namespace end
{
    class Matrix4
    {
    public:

        enum ENTRIES
        {
            _11=0,  _12,  _13,  _14,
            _21,    _22,    _23,    _24,
            _31,    _32,    _33,    _34,
            _41,    _42,    _43,    _44
        };

        //////////////////////////////////////////////////////////////////////
        // 단위행렬 / 영행렬 ---
        //
        void makeIdentity();
        void makeZero();


        //////////////////////////////////////////////////////////////////////
        // 주어진 행렬로부터 행렬을 만드는 경우 ---
        //
        void makeFromInverse( const Matrix4& _rMatToGetInvers );
        void makeFromMultiply(
                const
Matrix4* _pMat1,
                const Matrix4* _pMat2,
                const Matrix4* _pMat3NullIfNotUse = 0,
                const Matrix4* _pMat4NullIfNotUse = 0,
                const Matrix4* _pMat5NullIfNotUse = 0 );


        //////////////////////////////////////////////////////////////////////
        // 변환의 용도로 쓰일 행렬을 만드는 경우 ---
        //
        void makeTransform( const Matrix4& _rMat );

        void makeTransformPerspectiveProjectionLH(
                float _fFieldOfViewRadians = END_PI/4.f,
                float _fAspectRatio = 4.f/3.f,
                float _fZNear = 1.0f, float _fZFar = 1000.0f );
        void makeTransformPerspectiveProjectionRH(
                float _fFieldOfViewRadians = END_PI/4.f,
                float _fAspectRatio = 4.f/3.f,
                float _fZNear = 1.0f, float _fZFar = 1000.0f );

        void makeTransformOrthogonalProjectionLH(
                float _fWidth = 800.0f, float _fHeight = 600.0f,
                float _fZNear = 0.0f, float _fZFar = 1.0f );
        void makeTransformOrthogonalProjectionRH(
                float _fWidth = 800.0f, float _fHeight = 600.0f,
                float _fZNear = 0.0f, float _fZFar = 1.0f );

        void makeTransformViewLH(
                const Vector3& _rPosition,
                const Vector3& _rDir,
                const Vector3& _rUp );
        void makeTransformViewRH(
                const Vector3& _rPosition,
                const Vector3& _rDir,
                const Vector3& _rUp );

        void makeTransformCoordinateSystem(
                const Vector3& _rOrigin,
                const Vector3& _rX,
                const Vector3& _rY,
                const Vector3& _rZ );


        //////////////////////////////////////////////////////////////////////
        // 행렬연산 ---
        //
        void multiply( const Matrix4& _rMatToMultiply );
        void transformVector3( Vector3& _rOutVecToTransform );
        void transformVector4( Vector4& _rOutVecToTransform );

        /*  00, 01, 02, 03    =   11, 12, 13, 14
            04, 05, 06, 07  = 21, 22, 23, 24
            08, 09, 10, 11  = 31, 32, 33, 34
            12, 13, 14, 15  = 41, 42, 43, 44   */

        float Entries[16];
    };
}


음... 나름 괜찮다고 생각중.. 특히 저 makeFromMultiply는 최적화를 잘해줘서 불필요한 임시객체 생성을 막을수 있을듯.

프로그래밍 게임개발, 프로그래밍, 행렬