matrix4x4 Multiply question help

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
feelthat
Posts: 194
Joined: Sat Feb 02, 2013 5:27 am

matrix4x4 Multiply question help

Post by feelthat »

core::matrix4 a;
core::matrix4 b;
core::matrix4 c;

c = a * b;

//in matrix4.h

inline CMatrix4<T> CMatrix4<T>::operator*(const CMatrix4<T>& m2) const
{
#if defined ( USE_MATRIX_TEST )
// Testing purpose..
if ( this->isIdentity() )
return m2;
if ( m2.isIdentity() )
return *this;
#endif

CMatrix4<T> m3 ( EM4CONST_NOTHING );

const T *m1 = M;

m3[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
m3[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
m3[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
m3[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];

m3[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
m3[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
m3[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
m3[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];

m3[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
m3[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
m3[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
m3[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];

m3[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
m3[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
m3[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
m3[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];
return m3;
}

why the matrix multiply is not normal ????

like follows is normal
http://www.calcul.com/show/calculator/m ... n_;4;4;4;4

const float _m0 = (m0 * B.m0 + m1 * B.m4 + m2 * B.m8 + m3 * B.m12);
const float _m1 = (m0 * B.m1 + m1 * B.m5 + m2 * B.m9 + m3 * B.m13);
const float _m2 = (m0 * B.m2 + m1 * B.m6 + m2 * B.m10 + m3 * B.m14);
const float _m3 = (m0 * B.m3 + m1 * B.m7 + m2 * B.m11 + m3 * B.m15);
const float _m4 = (m4 * B.m0 + m5 * B.m4 + m6 * B.m8 + m7 * B.m12);
const float _m5 = (m4 * B.m1 + m5 * B.m5 + m6 * B.m9 + m7 * B.m13);
const float _m6 = (m4 * B.m2 + m5 * B.m6 + m6 * B.m10 + m7 * B.m14);
const float _m7 = (m4 * B.m3 + m5 * B.m7 + m6 * B.m11 + m7 * B.m15);
const float _m8 = (m8 * B.m0 + m9 * B.m4 + m10 * B.m8 + m11 * B.m12);
const float _m9 = (m8 * B.m1 + m9 * B.m5 + m10 * B.m9 + m11 * B.m13);
const float _m10 = (m8 * B.m2 + m9 * B.m6 + m10 * B.m10 + m11 * B.m14);
const float _m11 = (m8 * B.m3 + m9 * B.m7 + m10 * B.m11 + m11 * B.m15);
const float _m12 = (m12 * B.m0 + m13 * B.m4 + m14 * B.m8 + m15 * B.m12);
const float _m13 = (m12 * B.m1 + m13 * B.m5 + m14 * B.m9 + m15 * B.m13);
const float _m14 = (m12 * B.m2 + m13 * B.m6 + m14 * B.m10 + m15 * B.m14);
const float _m15 = (m12 * B.m3 + m13 * B.m7 + m14 * B.m11 + m15 * B.m15);
Last edited by feelthat on Wed Dec 03, 2014 10:06 pm, edited 1 time in total.
CuteAlien
Admin
Posts: 9634
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: matrix question help

Post by CuteAlien »

There is a code tag in the forum which you can use to make code in your posts more readable.

And please try to explain exactly what you mean and what this is about. Saying "why the matrix multiply is not normal" doesn't tell me anything. You just post lot's of lines without explaining what is actually different. I checked a few of those lines and they did the exact same calculations, but maybe one line is different? Please say which one. You are not even giving a single example where it will give different results. Or any explanation why you think our version is wrong. I really have no idea what you are trying to say with your post...

I mean we obviously all use matrix multitplication a lot and so far it worked.
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
feelthat
Posts: 194
Joined: Sat Feb 02, 2013 5:27 am

Re: matrix question help

Post by feelthat »

Matrix 4x4
m3 = m1 * m2 normally -> http://snipd.net/matrix-multiplication-in-c

m3[0] = m1[0]*m2[0] + m1[1]*m2[4] + m1[2]*m2[8] + m1[3]*m2[12];
m3[1] = m1[0]*m2[1] + m1[1]*m2[5] + m1[2]*m2[9] + m1[3]*m2[13];
m3[2] = m1[0]*m2[2] + m1[1]*m2[6] + m1[2]*m2[10] + m1[3]*m2[14];
m3[3] = m1[0]*m2[3] + m1[1]*m2[7] + m1[2]*m2[11] + m1[3]*m2[15];

m3[4] = m1[4]*m2[0] + m1[5]*m2[4] + m1[6]*m2[8] + m1[7]*m2[12];
m3[5] = m1[4]*m2[1] + m1[5]*m2[5] + m1[6]*m2[9] + m1[7]*m2[13];
m3[6] = m1[4]*m2[2] + m1[5]*m2[6] + m1[6]*m2[10] + m1[7]*m2[14];
m3[7] = m1[4]*m2[3] + m1[5]*m2[7] + m1[6]*m2[11] + m1[7]*m2[15];

m3[8] = m1[8]*m2[0] + m1[9]*m2[4] + m1[10]*m2[8] + m1[11]*m2[12];
m3[9] = m1[8]*m2[1] + m1[9]*m2[5] + m1[10]*m2[9] + m1[11]*m2[13];
m3[10] = m1[8]*m2[2] + m1[9]*m2[6] + m1[10]*m2[10] + m1[11]*m2[14];
m3[11] = m1[8]*m2[3] + m1[9]*m2[7] + m1[10]*m2[11] + m1[11]*m2[15];

m3[12] = m1[12]*m2[0] + m1[13]*m2[4] + m1[14]*m2[8] + m1[15]*m2[12];
m3[13] = m1[12]*m2[1] + m1[13]*m2[5] + m1[14]*m2[9] + m1[15]*m2[13];
m3[14] = m1[12]*m2[2] + m1[13]*m2[6] + m1[14]*m2[10] + m1[15]*m2[14];
m3[15] = m1[12]*m2[3] + m1[13]*m2[7] + m1[14]*m2[11] + m1[15]*m2[15];

///

but in matrix.h is become~~~

m3 = m2 * m1

m3[0] = m1[0]*m2[0] + m1[4]*m2[1] + m1[8]*m2[2] + m1[12]*m2[3];
m3[1] = m1[1]*m2[0] + m1[5]*m2[1] + m1[9]*m2[2] + m1[13]*m2[3];
m3[2] = m1[2]*m2[0] + m1[6]*m2[1] + m1[10]*m2[2] + m1[14]*m2[3];
m3[3] = m1[3]*m2[0] + m1[7]*m2[1] + m1[11]*m2[2] + m1[15]*m2[3];

m3[4] = m1[0]*m2[4] + m1[4]*m2[5] + m1[8]*m2[6] + m1[12]*m2[7];
m3[5] = m1[1]*m2[4] + m1[5]*m2[5] + m1[9]*m2[6] + m1[13]*m2[7];
m3[6] = m1[2]*m2[4] + m1[6]*m2[5] + m1[10]*m2[6] + m1[14]*m2[7];
m3[7] = m1[3]*m2[4] + m1[7]*m2[5] + m1[11]*m2[6] + m1[15]*m2[7];

m3[8] = m1[0]*m2[8] + m1[4]*m2[9] + m1[8]*m2[10] + m1[12]*m2[11];
m3[9] = m1[1]*m2[8] + m1[5]*m2[9] + m1[9]*m2[10] + m1[13]*m2[11];
m3[10] = m1[2]*m2[8] + m1[6]*m2[9] + m1[10]*m2[10] + m1[14]*m2[11];
m3[11] = m1[3]*m2[8] + m1[7]*m2[9] + m1[11]*m2[10] + m1[15]*m2[11];

m3[12] = m1[0]*m2[12] + m1[4]*m2[13] + m1[8]*m2[14] + m1[12]*m2[15];
m3[13] = m1[1]*m2[12] + m1[5]*m2[13] + m1[9]*m2[14] + m1[13]*m2[15];
m3[14] = m1[2]*m2[12] + m1[6]*m2[13] + m1[10]*m2[14] + m1[14]*m2[15];
m3[15] = m1[3]*m2[12] + m1[7]*m2[13] + m1[11]*m2[14] + m1[15]*m2[15];

/////////

here is a test can try
http://www.calcul.com/show/calculator/m ... n_;4;4;4;4

so why matrix.h is not normal Matrix multiplication

CuteAlien wrote:There is a code tag in the forum which you can use to make code in your posts more readable.

And please try to explain exactly what you mean and what this is about. Saying "why the matrix multiply is not normal" doesn't tell me anything. You just post lot's of lines without explaining what is actually different. I checked a few of those lines and they did the exact same calculations, but maybe one line is different? Please say which one. You are not even giving a single example where it will give different results. Or any explanation why you think our version is wrong. I really have no idea what you are trying to say with your post...

I mean we obviously all use matrix multitplication a lot and so far it worked.
Last edited by feelthat on Wed Dec 03, 2014 9:52 pm, edited 1 time in total.
CuteAlien
Admin
Posts: 9634
Joined: Mon Mar 06, 2006 2:25 pm
Location: Tübingen, Germany
Contact:

Re: matrix question help

Post by CuteAlien »

No, your link is no test, it's just an empty matrix. But I think I get it - it's about pre vs post multiplication. I think this has to do with Irrlicht having matrices in row major order (like D3D and unlike OpenGL). There is no normal way - there are just different ways to do this stuff (which is the reason why opengl and d3d did it different which is a constant pain).

edit: Reason is probably simply that D3D was supported before opengl. But this stuff was all done long before my time in the Irrlicht team and I'm no expert when it comes to matrix math (I only know how to use them).
IRC: #irrlicht on irc.libera.chat
Code snippet repository: https://github.com/mzeilfelder/irr-playground-micha
Free racer made with Irrlicht: http://www.irrgheist.com/hcraftsource.htm
feelthat
Posts: 194
Joined: Sat Feb 02, 2013 5:27 am

Re: matrix question help

Post by feelthat »

thanks

but when use the different ways to do multiplication then

C = A * B(pre) will become C = B * A(post)

and i see the matrix multiplication in Driect3D also use normal pre multiplication
http://www.gamedev.net/topic/571689-pro ... ormations/

public static Matrix MatrixMultiply( Matrix a, Matrix b )
{
Matrix result = new Matrix();

result.m11 = a.m11*b.m11 + a.m12*b.m21 + a.m13*b.m31 + a.m14*b.m41;
result.m12 = a.m11*b.m12 + a.m12*b.m22 + a.m13*b.m32 + a.m14*b.m42;
result.m13 = a.m11*b.m13 + a.m12*b.m23 + a.m13*b.m33 + a.m14*b.m43;
result.m14 = a.m11*b.m14 + a.m12*b.m24 + a.m13*b.m34 + a.m14*b.m44;

result.m21 = a.m21*b.m11 + a.m22*b.m21 + a.m23*b.m31 + a.m24*b.m41;
result.m22 = a.m21*b.m12 + a.m22*b.m22 + a.m23*b.m32 + a.m24*b.m42;
result.m23 = a.m21*b.m13 + a.m22*b.m23 + a.m23*b.m33 + a.m24*b.m43;
result.m24 = a.m21*b.m14 + a.m22*b.m24 + a.m23*b.m34 + a.m24*b.m44;

result.m31 = a.m31*b.m11 + a.m32*b.m21 + a.m33*b.m31 + a.m34*b.m41;
result.m32 = a.m31*b.m12 + a.m32*b.m22 + a.m33*b.m32 + a.m34*b.m42;
result.m33 = a.m31*b.m13 + a.m32*b.m23 + a.m33*b.m33 + a.m34*b.m43;
result.m34 = a.m31*b.m14 + a.m32*b.m24 + a.m33*b.m34 + a.m34*b.m44;

result.m41 = a.m41*b.m11 + a.m42*b.m21 + a.m43*b.m31 + a.m44*b.m41;
result.m42 = a.m41*b.m12 + a.m42*b.m22 + a.m43*b.m32 + a.m44*b.m42;
result.m43 = a.m41*b.m13 + a.m42*b.m23 + a.m43*b.m33 + a.m44*b.m43;
result.m44 = a.m41*b.m14 + a.m42*b.m24 + a.m43*b.m34 + a.m44*b.m44;

return result;
}

I am still confused why?

and in COGLES2FixedPipelineRenderer.cpp can see

const core::matrix4 W = driver->getTransform(ETS_WORLD);
const core::matrix4 V = driver->getTransform(ETS_VIEW);
const core::matrix4 P = driver->getTransform(ETS_PROJECTION);
core::matrix4 Matrix = P * V * W;
services->setPixelShaderConstant(WVPMatrixID, Matrix.pointer(), 16);

if pre multiplication will like
core::matrix4 Matrix = W * V * P;

here is sequence~
http://www.opengl-tutorial.org/beginner ... -matrices/

need answer any one help me?
CuteAlien wrote:No, your link is no test, it's just an empty matrix. But I think I get it - it's about pre vs post multiplication. I think this has to do with Irrlicht having matrices in row major order (like D3D and unlike OpenGL). There is no normal way - there are just different ways to do this stuff (which is the reason why opengl and d3d did it different which is a constant pain).

edit: Reason is probably simply that D3D was supported before opengl. But this stuff was all done long before my time in the Irrlicht team and I'm no expert when it comes to matrix math (I only know how to use them).
feelthat
Posts: 194
Joined: Sat Feb 02, 2013 5:27 am

Re: matrix question help

Post by feelthat »

I think I got answer

this is because for GLSL shader language is column-major order

gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;

and in irrlicht WORLD matrix is Model Matrix


http://www.songho.ca/opengl/gl_matrix.html
http://www.swiftless.com/tutorials/open ... rices.html


feelthat wrote:thanks

but when use the different ways to do multiplication then

C = A * B(pre) will become C = B * A(post)

and i see the matrix multiplication in Driect3D also use normal pre multiplication
http://www.gamedev.net/topic/571689-pro ... ormations/

public static Matrix MatrixMultiply( Matrix a, Matrix b )
{
Matrix result = new Matrix();

result.m11 = a.m11*b.m11 + a.m12*b.m21 + a.m13*b.m31 + a.m14*b.m41;
result.m12 = a.m11*b.m12 + a.m12*b.m22 + a.m13*b.m32 + a.m14*b.m42;
result.m13 = a.m11*b.m13 + a.m12*b.m23 + a.m13*b.m33 + a.m14*b.m43;
result.m14 = a.m11*b.m14 + a.m12*b.m24 + a.m13*b.m34 + a.m14*b.m44;

result.m21 = a.m21*b.m11 + a.m22*b.m21 + a.m23*b.m31 + a.m24*b.m41;
result.m22 = a.m21*b.m12 + a.m22*b.m22 + a.m23*b.m32 + a.m24*b.m42;
result.m23 = a.m21*b.m13 + a.m22*b.m23 + a.m23*b.m33 + a.m24*b.m43;
result.m24 = a.m21*b.m14 + a.m22*b.m24 + a.m23*b.m34 + a.m24*b.m44;

result.m31 = a.m31*b.m11 + a.m32*b.m21 + a.m33*b.m31 + a.m34*b.m41;
result.m32 = a.m31*b.m12 + a.m32*b.m22 + a.m33*b.m32 + a.m34*b.m42;
result.m33 = a.m31*b.m13 + a.m32*b.m23 + a.m33*b.m33 + a.m34*b.m43;
result.m34 = a.m31*b.m14 + a.m32*b.m24 + a.m33*b.m34 + a.m34*b.m44;

result.m41 = a.m41*b.m11 + a.m42*b.m21 + a.m43*b.m31 + a.m44*b.m41;
result.m42 = a.m41*b.m12 + a.m42*b.m22 + a.m43*b.m32 + a.m44*b.m42;
result.m43 = a.m41*b.m13 + a.m42*b.m23 + a.m43*b.m33 + a.m44*b.m43;
result.m44 = a.m41*b.m14 + a.m42*b.m24 + a.m43*b.m34 + a.m44*b.m44;

return result;
}

I am still confused why?

and in COGLES2FixedPipelineRenderer.cpp can see

const core::matrix4 W = driver->getTransform(ETS_WORLD);
const core::matrix4 V = driver->getTransform(ETS_VIEW);
const core::matrix4 P = driver->getTransform(ETS_PROJECTION);
core::matrix4 Matrix = P * V * W;
services->setPixelShaderConstant(WVPMatrixID, Matrix.pointer(), 16);

if pre multiplication will like
core::matrix4 Matrix = W * V * P;

here is sequence~
http://www.opengl-tutorial.org/beginner ... -matrices/

need answer any one help me?
CuteAlien wrote:No, your link is no test, it's just an empty matrix. But I think I get it - it's about pre vs post multiplication. I think this has to do with Irrlicht having matrices in row major order (like D3D and unlike OpenGL). There is no normal way - there are just different ways to do this stuff (which is the reason why opengl and d3d did it different which is a constant pain).

edit: Reason is probably simply that D3D was supported before opengl. But this stuff was all done long before my time in the Irrlicht team and I'm no expert when it comes to matrix math (I only know how to use them).
Post Reply