Row and Column matrix conventions in RenderMan

February 7th, 2002 § 0 comments

I am the very model of a modern Major-General,
I’ve information vegetable, animal, and mineral
– The Pirates of Penzance, Gilbert & Sullivan

Judging by the documents on the Web and on USENET that claim or deny that RenderMan and OpenGL share the same matrix conversions, there appears to be some confusion about matrix convention ordering in RenderMan – even among people who should know better. This is an attempt to clear that up.

RenderMan assumes points are row vectors

First of all, the RenderMan Interface Specification assumes points are row vectors. This affects how the matrix looks in its mathematical form on paper. In this convention, when multiplying points (in the mathematical paper sense), the point goes on the left as a row vector, and the matrix goes on the right. This also means that the translation part of a transformation goes on the bottom:

|sx 0  0  0 |
|0  sy 0  0 |
|0  0  sz 0 |
|dx dy dz 1 |

Note that this is NOT the same convention used by modern linear algebra textbooks, Foley & VD (2nd edition, not the 1st), and the OpenGL documentation. It is the same as Newman & Sproull and many other older, but influential, graphics text books.

RenderMan uses row major ordering

Row major ordering means that the matrix is stored in memory such that row elements are packed together contiguously – i.e. a float m[16] would correspond to the matrix:

|m[0]  m[1]  m[2]  m[3] |
|m[4]  m[5]  m[6]  m[7] |
|m[8]  m[9]  m[10] m[11]|
|m[12] m[13] m[14] m[15]|

Whereas in column major mode, it’s the column elements which are packed together contiguously:

|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]|

C programmers are probably more comfortable with the former representation, because multidimension arrays are indexed in the same sort of order in memory. That is, as the memory address increases, the rightmost subscript increments the fastest. Thus, in a float m[4][4], m[0][0] and m[0][1] are next to each other. On the other hand, Fortran programmers are more comfortable with the second, because as the memory address increases, the leftmost subscript increments.

This gets us to OpenGL. OpenGL uses column major ordering to represent matrices in memory. I believe the only time you really need to worry about this is if you pass a matrix directly to OpenGL using glLoadMatrix or glMultMatrix; you’ll have to pass in 16 numbers in column major order.

The RenderMan C API binding, on the other hand, uses row major ordering. This is most obvious in the RIB binding for RiConcatTransform, where the 16 elements are passed in using row major order.

So if you’re using RenderMan, and you’re a C programmer using the RtMatrix type, it should be straight forward to think of an RtMatrix m corresponding directly to the mathematical representation:

|m[0][0] m[0][1] m[0][2] m[0][3]|
|m[1][0] m[1][1] m[1][2] m[1][3]|
|m[2][0] m[2][1] m[2][2] m[2][3]|
|m[3][0] m[3][1] m[3][2] m[3][3]|
      

But it’s all the same thing in the end!

It is somewhat surprising to learn, given all of the above, that the exact same code can be used in OpenGL to multiply a matrix and a point as can be used in RenderMan. Observe that in RenderMan, you have:

                    |m[0][0] m[0][1] m[0][2] m[0][3]|
v[0] v[1] v[2] v[3] |m[1][0] m[1][1] m[1][2] m[1][3]|
                    |m[2][0] m[2][1] m[2][2] m[2][3]|
                    |m[3][0] m[3][1] m[3][2] m[3][3]|
    

whereas in OpenGL, you have:

       |m[0][0] m[1][0] m[2][0] m[3][0]|   |v[0]|
       |m[0][1] m[1][1] m[2][1] m[3][1]|   |v[1]|
       |m[0][2] m[1][2] m[2][2] m[3][2]|   |v[2]|
       |m[0][3] m[1][3] m[2][3] m[3][3]|   |v[3]|
    

Note that it would end up being the same code in both cases. So RenderMan does work just like OpenGL, internally. It’s just not very obvious, and you need to be careful about how you present your matrices to each respective API.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

What's this?

You are currently reading Row and Column matrix conventions in RenderMan at levork.org.

meta

  • Pages

  • Archives

  • Categories

  • Flickr