Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The book uses column-major order for matrices, while three.js docs use row-order #27

Open
w2xi opened this issue Aug 27, 2021 · 4 comments

Comments

@w2xi
Copy link

w2xi commented Aug 27, 2021

Describe the bug
When i was reading about transformation matrices topic in this book, i found that the description of formula of X-Rotation has a little difference with the makeRotationX method of Matrix4 class in official docs. I didn't know which one was correct. So, i report a issue here now.

Screenshots
Transformation Matrices
screenshot-discoverthreejs com-2021 08 27-10_08_02

makeRotationX method of Matrix4 class
screenshot-threejs org-2021 08 27-12_58_56

@looeee
Copy link
Owner

looeee commented Aug 27, 2021

Hey, good catch. Actually neither is incorrect - the difference is because there are two conventions for writing matrices called row-major and column-major ordering.

Internally, three.js matrices are stored in column-major order. However, for some reason the matrix.set method takes the elements in row-major order and internally converts them to column-major (I'm sure there's a good reason for that but I don't know it 😅).

If the 4x4 matrix is made up of four vectors:

X = (a,b,c,d)
Y = (e,f,g,h)
Z = (i,j,k,l)
W = (m,n,o,p)

Then we can write the matrix in row major order (each vector makes up a row):

Mr = (
    a, b, c, d,
    e, f, g, h, 
    i, j, k, l,
    m,n,o,p
)

Or column-major order (each vector makes up a column):

Mc = (
    a, e, i, m,   
    b, f, j, n, 
    c, g, k, o, 
    d, h, l, p
)

Then a transformation matrix representing an X rotation around θ can be written either in row major order:

ROTXr = (
    1, 0, 0, 0,
    0, cos(θ), -sin(θ), 0,
    0, sin(θ), cos(θ), 0,
    0, 0, 0, 1
)

or in column major order:

ROTXc = (
    1, 0, 0, 0,
    0, cos(θ), sin(θ), 0,
    0, -sin(θ), cos(θ), 0,
    0, 0, 0, 1
)

The docs follow the Matrix4.set method and everything is written in row-major order. However, in the book I've written things in column-major to match the way they are stored internally, and also because all of the reference books I checked (and wikipedia) write matrices in column major order.

So there's two choices here:

A. Current situation: write matrices to match the literature (e.g. realtime rendering book, wikipedia, several game math books that I checked)
B. Switch over the write matrices the way the three.js docs do even though it's less common

Neither one of these is correct so I'm open to suggestions.

@looeee
Copy link
Owner

looeee commented Aug 28, 2021

I tracked down the original reasoning here, way back in 2013.

mrdoob/three.js#3814 (comment)

Originally three.js stored matrices internally in row-major (I guess from pre-WebGL days) but then switched (in r49) to column-major for efficiency and to match other WebGL/OpenGL libraries. To help with backwards compatibility they kept the .set method as row-major.

@w2xi
Copy link
Author

w2xi commented Aug 28, 2021

Thanks your reply.
I just found out It seems to be explained that the reason why it does with this in docs.
screenshot-threejs org-2021 08 28-12_44_53

@w2xi
Copy link
Author

w2xi commented Aug 28, 2021

Thanks to the work you have done.
I am new to threejs. This book covers everything as I need to get started. Great!
it helped me a lot so far, thanks.

@looeee looeee changed the title [BUG, ERROR] The formula of X-Rotation may be incorrect in 'Transformation Matrices' topic The book uses column-major order for matrices, while three.js docs use row-order Sep 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants