Help needed setting up camera transform

Started by
5 comments, last by Burnt_Fyr 11 years, 4 months ago

First time poster here. I tried searching the forum for prior posts related to this, but didn't find exactly what I needed.

I am trying to make a simple 3d rendering engine just to demonstrate to myself that I understand the math. I have not taken linear algebra, but have spent some time trying to self-teach with online and textbook tutorials and have a working understanding (I think). I am writing this simple engine with lazarus free pascal.

I have found several tutorials that I have tried reading through. Most recently from www.scratchapixel.com.

First I have objects that are positioned in the world with a world transform/matrix.

Next I am trying to set up my camera transform. But I am apparently doing something wrong. I am hoping that if I write out my understanding here, someone can pick up where I am off.

First, I am planning on using a right-handed matrix and math. I think this means that when I consider the axis at (0,0,0), +X will go to the "right", +Y will go "up", and +Z will come "out towards me".

Next, I think that to create the camera transform, one has to create cardinal vectors for the new coordinate space: In, Up, and Left.

In = LookingAtPosition - Camera Position

Left = In X (0,1,0) (in vector cross a global up vector)

Up = in X Left

Next, I think that the parts of a matrix are as follows. But I am uncertain about this.

[Left.x, Left.z, Left.z, A ]

[ Up.x, Up.y, Up.z, B ]

[ In.x, In.x, In.z, C ]

[ 0, 0, 0, 1 ]

A,B,C as a column vector is the position of the camera. (e.g. A=T.x, B=T.y, C=T.z)

I have some output from the engine, but this web page interface won't let me paste the text in. (I assume this is a defense against spammers).

Before I go any further, can anyone comment on my understanding so far?

Any help appreciated.

Kevin T

Advertisement

Normally the camera is set using a perspective matrix and a view matrix.

A can't really explain the details but if you want, you can check the glm library.

I know it is for C++, but you can open the header files (it is a library containing only header files), and see in particular how the glm::perspective() and glm::lookat() work, you can then multiply the two matrices and get the view matrix which is the camera matrix.

They're located in the gtc/matrix_transform.hpp file.

Hope it helps.

Normally the camera is set using a perspective matrix and a view matrix.

A can't really explain the details but if you want, you can check the glm library.

I know it is for C++, but you can open the header files (it is a library containing only header files), and see in particular how the glm::perspective() and glm::lookat() work, you can then multiply the two matrices and get the view matrix which is the camera matrix.

They're located in the gtc/matrix_transform.hpp file.

Hope it helps.

Thanks for the feedback. I'll see if I can find code examples.

I am trying to separate the view matrix and perspective matrix to ensure I understand each separately.

Thanks

Kevin

Hi Kevin,

I hope I am not too late to help you with your problem/question. You did right to watch on scratchapixel but you should look at this page in particular:

http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-4-geometry/conventions-again-row-major-vs-column-major-vector/

Basically knowing whether you use a right or left hand coordinate system is indeed important but in fact, in that particular case, it has little to do with whether you matrix is correct or not. What is important for constructing your matrix from the 3 vectors (up, right, forward) is whether you renderer uses row- or column-major notation for matrices. As mentioned in the page above if you use the row-major notation, your 3 vectors should be written vertically in the matrix and if you use column-major they should be written horizontally. In other words, assuming you have the vectors A B C (representing the right, top and forward vector from your camera coordinate system) you should write:

Ax Bx Cx
Ay By Cy
Az Bz Cz


If you use row-major notation. Now I will explain you why (there's a way an easy of checking how you should write the matrix if you can't remember it by heart). Remember that if you use row-major vector then the vector-matrix multiplication needs to be written as:

|Ax Ay Az|
V[x y z] M |Bx By Bz| [EDITED: changed from original post]
|Cx Cy Cz|

Where A is Right Vector, B is Up Vector and C is Forward Vector

Computing the multiplication can be done like that:

V'x = Vx * Ax + Vy * Bx + Vz * Cx
V'y = Vx * Ay + Vy * By + Vz * Cy [EDITED: changed from original post]
V'z = Vx * Az + Vy * Bz + Vz * Cz

EDITED FROM HERE:

I guess I was a bit too quick yesterday when I replied and my demonstration was actually wrong. Talking to the guys from work, they showed me a better way of checking that this is the right way of writing the matrix if you use a row-major notation for matrices. The default cartesian coordinate system should be like that:

Y (up 0, 1, 0)
^
|
|----> X (right 1, 0, 0)
/
/
Z (forward 1, 0, 0)

If you have a camera you would be looking down the z-axis. Now you can imagine that your camera is looking down the x-axis. Therefore the right vector for this camera becomes (0, 0, -1), the Up vector is still (0, 1, 0) and the Forward vector becomes the x-axis (1, 0, 0):


Up Right
^ / \
| / \
|/----> Fwd > camera
/
/

Now if you right these vectors as a matrix you get:
|Rx Ry Rz| |0 0 -1|
M = |Ux Uy Yz| = |0 1 0|
|Fx Fy Fz| |1 0 0|

This matrix is called the camera-to-world matrix.

The demonstration to check that this is correct is a bit complicated so I thought I would first quickly correct my original post to avoid leading you and other people on the wrong track. I will post the demonstration later today.

Sorry for having (probably) confused you (even more). Anyway, bottom line is that if you use row-major notation for your vectors and matrices (and assuming a right-hand coordinate system) as you mentioned, then this is the "proper" way of writing the camera-to-world matrix from the right, up and fwd vector.

One tip though. I am always (and I proved it) myself very confused about these things. I found scratchapixel very useful but I am also often using Maya to check the accuracy of my code. For instance in that case, you can create a default camera, rotate it around the y-axis by 90 degrees CCW, and check the resulting world matrix with the following mel code: getAttr camera.worldMatrix;

Because Maya uses row-major and uses the right hand coordinate system, if you use the same standard, then the result you get should mach your code and what you use.

Mast4ss,

Thanks so much for this great reply. It has helped me greatly. I read the section about column major vs row major, and that explains a lot. I have been using this math textbook, and it has always presented the math in column major format, and didn't discuss row major at all. I had seen the concept mentioned before, but when I looked it up on Wikipedia, it seemed to be discussing the *computing* aspect of row vs column major, i.e. how the matrix is laid out in memory. So a big thanks for this.

http://www.amazon.com/Mathematics-Programming-Computer-Graphics-Development/dp/1584500379

It also explains why I was getting confused when looking at different web site tutorial pages. Some would be in column major, and some in row major, and had not explicitly mentioned which format they were using.

Hi Kevin,

I hope I am not too late to help you with your problem/question. You did right to watch on scratchapixel but you should look at this page in particular:

http://www.scratchapixel.com/lessons/3d-basic-lessons/lesson-4-geometry/conventions-again-row-major-vs-column-major-vector/

Basically knowing whether you use a right or left hand coordinate system is indeed important but in fact, in that particular case, it has little to do with whether you matrix is correct or not. What is important for constructing your matrix from the 3 vectors (up, right, forward) is whether you renderer uses row- or column-major notation for matrices.

As mentioned in the page above if you use the row-major notation, your 3 vectors should be written vertically in the matrix and if you use column-major they should be written horizontally.

//kt Are you sure about the above statements? After reading the ScratchAPixel site, I think that in column major, the columns represent the basis (axes). The page has a helpful table at the end that summarizes the difference, and states this explicitly

In other words, assuming you have the vectors A B C (representing the right, top and forward vector from your camera coordinate system) you should write:

Ax Bx Cx
Ay By Cy
Az Bz Cz


If you use row-major notation.

Yes. I agree with this.

Now I will explain you why (there's a way an easy of checking how you should write the matrix if you can't remember it by heart). Remember that if you use row-major vector then the vector-matrix multiplication needs to be written as:

...

The example was helpful.

Hope it helps a bit. This should be maybe clearer on scratchapixel indeed. I would be you I would contact them and asked them questions when you don't know or can't find information on their website. I work with them and know they are keen on improving their website, etc.

Hope I didn't make things more messy in your mind though ;-)

This has been very helpful. I have written my own vector and matrix classes, and I am using column major format. I am going to go back through my matrix setup and make sure I am being consistent.

I am heading our for a skiing trip, :-) , in a few days, so I may not get to work on this for few weeks. But I'll try to post back on my progress later.

One other quick question before I go, regarding the right hand rule.

When I put my right hand into the right-hand position (a quick google search of right hand rule images demonstrates what I am talking about), I have my thumb pointing upward, my index finger pointing "in" and my middle finger is pointing to the left. In another graphics engine I used to work with, Genesis3d (http://www.genesis3d.com/~kdtop/ ) there were functions for GetIn, GetLeft, GetUp. So it seemed that up-in-left were the names used to describe the orientation of a matrix. But this is different from most tutorials that I am now reading that describe up-in-right.

If I consider my thumb to be the x axis, my index finger the y axis, and my middle finger to be the z axis, and then rotate my hand such that it corresponds with the typical display of the x, y, and z axes, then it seems that there would be this mapping:

Thumb -- x-axis -- "right"

index finger -- y axis -- "up"

middle finger -- z axis -- "out"

Is this different, or just an orientation variance? In your post, and in many others, you mention "up, forward, right", but this seems different from up-in-left.

Thanks again so much for your help (and for anyone else that cares to comment).

Kevin (kdtop)

Kevin by talking to the guys today I realised I made a mistake in my explanation. I amended the post above. Sorry about that. Please, if you find the time go through it again. You say you use column-major rather than row-major. The explanation I gave works for row-major so technically you will need to transpose the matrix. If other words for column major your matrix should be written with the basis vectors vertically:

|Rx Ux Fx|
M =|Ry Uy Fy| if you use column-major
|Rz Uz Fz|

Them matrix mult should be written as

|Rx Ux Fx| |Vx|
M * V = |Ry Uy Fy| * |Vy|
|Rz Uz Fz| |Vz|

For the right- left-hand naming convention I would also have a look at this page:

http://scratchapixel.com/lessons/3d-basic-lessons/lesson-4-geometry/math-operations-on-points-and-vectors/

Now from my understanding, there's a lot of people out there using different names for the same thing which is very confusing. That's why I like to refer to this page and try to stick to their convention which seems to be following some of the industry standards. Hopefully what's in their website is accurate and reliable ;-)

Do not confuse row majorness, with row vectors, as one defines how it is stored in an array(whether m[0]m[1]m[2]m[3] or m[0]m[4]m[8]), and the other relates to how things are multiplied, ie; column vectors are multiplied with matrix rows.

This topic is closed to new replies.

Advertisement