5

I am having problems setting the camera such that it points at the origin O(0,0,0) with a degree of 45° to all other axes with all coordinates positive (which should have the same value, of course). You can see in the image the closest I've got

enter image description here

However, as you can see, the x value is negative here, so the camera is on the wrong side of the YZ plane.

The complete compilable project can be found at this revision in a gist.

The relevant matrix multiplications done are

osg::Matrixd rotate_x(
        1.0, 0.0, 0.0, 0.0,
        0.0, q_cos, -q_sin, 0.0,
        0.0, q_sin, q_cos, 0.0,
        0.0, 0.0, 0.0, 1.0 
);
osg::Matrixd rotate_y(
        q_cos, 0.0, q_sin, 0.0,
        0.0, 1.0, 0.0, 0.0,
        -q_sin, 0.0, q_cos, 0.0,
        0.0, 0.0, 0.0, 1.0 
);
camera_pos = camera_pos * rotate_x;
camera_pos = camera_pos * rotate_y;

in the file Simple.cpp.

I'm trying to figure out how this works (both mathematically and programmatically). I would prefer solutions which rely as little as possible on openscenegraph, and more on the math side, as I'd like to do the maths myself at first, to get a real grasp of how it works. So no quaternions or other advanced stuff yet, which are not taught in a basic linear algebra university course.

genpfault
  • 51,148
  • 11
  • 85
  • 139
Flavius
  • 13,566
  • 13
  • 80
  • 126

2 Answers2

1

Your rotate_y matrix looks flipped to me.

Starting with rotation matrix from glRotate, I simplified the resulting matrix with xyz = (0,1,0), and I got this (in column major order (standard opengl notation)

 q_cos  0  q_sin   0 
 0      1  0       0 
-q_sin  0  q_cos   0
 0      0  0       1

However, you're supplying the same matrix in row major order:

osg::Matrixd rotate_y(
        q_cos,  0.0, q_sin,  0.0,
        0.0,    1.0, 0.0,    0.0,
        -q_sin, 0.0, q_cos,  0.0,
        0.0,    0.0, 0.0,    1.0
);

-q_sin should be element [2] of the matrix, and q_sin should be element [8], but it looks like you've flipped them.


EDIT

OpenGL and OSG typically represent matrices in column major format, when you see a 4x4 matrix, it is laid out like the following

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

Where [0] is the first element of the array, 1 is the second, etc.

When you create a matrix with OSG, you're defining 16 sequential memory elements, from [0] to [15]

osg::Matrixd rotate_y([0], [1], [2]......,[15]);

When you break up the command into 4 rows, it looks like this:

osg::Matrixd rotate_y(
   [0], [1], [2], [3],
   [4], [5], [6], [7],
   [8], [9], [10],[11],
   [12],[13],[14],[15] 
)

Do you see how this is transposed from the original column vector representation? You need to flip it because the 4x4 matrix examples you find are the internet are represented by column vectors, while you're currently uploading them as row vectors. It doesn't mean that what you're reading is 'wrong', it's just in a different representation.

Tim
  • 35,413
  • 11
  • 95
  • 121
  • well spotted! It worked. To keep the spirit of sharing, I've fixed in turn the wikipedia page http://en.wikipedia.org/w/index.php?title=Rotation_matrix&diff=503394799&oldid=502821752 which got me on the wrong track – Flavius Jul 21 '12 at 05:11
  • I think you should revert that wikipedia change, I think you misunderstood me. The article was correct before, you've just confused the order in which you upload your vertices. Your matrices are correct, you're just uploading them in transposed order. @Flavius – Tim Jul 21 '12 at 05:24
  • For anyone reading this and wondering about the maths, follow http://www.youtube.com/watch?v=kmb7npLq5Pw&list=PL55414BF49E0DCFEE&feature=mh_lolz . In 3D it's the same as in 2D, you only skip the axis you don't need to transform. – Flavius Jul 21 '12 at 05:25
  • you mean, the z axis is reaching out of the screen on its negative side? – Flavius Jul 21 '12 at 05:29
  • ok, so I've done what any sane programmer does in such situations: pretend he's dumb and that he's got it all wrong. So I started to put around a Point along all the axes x, y, z and -x, -y, -z, and it was drawn correctly. So the labels of the axes and the axes are correct. You can see my experiment at revision `00f0fa67f28`, in `Simple.cpp:122` you can go through all possibilities. So, what am I actually doing wrong? The only time I got it right was when I've swapped `-sin` and `sin` in the transformation matrix as you've said. – Flavius Jul 21 '12 at 06:41
  • @Flavius please see my edited answer and see if that makes more sense. If not, please search and read articles about 'column vector vs row vector notation'. – Tim Jul 21 '12 at 07:21
  • I was a little bit confused by you calling the numbers in the matrix "vertices", I thought you meant the vertices of the cross model. Why do you call them vertices? – Flavius Jul 21 '12 at 08:43
  • Oh, and why do you say only the `rotate_y` is wrong, but both definitions of `R_x` and `R_y` on wikipedia are right? I've used them both exactly as in the wikipedia article, and `R_x` worked, that one should have been flipped too. I'd like to correct the wiki article if there's a mistake (be it inconsistencies in the notation, it doesn't matter). – Flavius Jul 21 '12 at 08:53
  • "OpenGL and OSG typically represent matrices in column major format" Doesn't OSG use row-major format? – Adri C.S. Dec 10 '14 at 09:23
0

Rotation matrices rotate a point around the origin. Since you set your initial position to (0,0,500) and apply an x and y rotation, you will be rotating the point (0,0,500) around the origin by acos(q_cos) or asin(q_sin) radians.

Kyle
  • 1,978
  • 1
  • 18
  • 30
  • Why by `acos(q_cos)` or `asin(q_sin)` and not by `q_cos` or `q_sin`? And also, how to get the camera "on the other side" of the YZ plane? – Flavius Jul 20 '12 at 21:16