pointing the camera at O(0,0,0), 45 deg - c++

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

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.

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.

Related

Bullet | Rigidbody translated correctly but printed position is wrong

I have a very simple problem, but I can't see what I'm doing wrong.
I have a rigidbody starting at pos: 0.0, 3.0, 0.0. I apply a translate, -90 degree rotation, and then another translate. The rigidbody's final position should be 2.0, 1.0, 0.0, but the position that is printed out is still 0.0, 3.0, 0.0.
I perform a collision test by dropping some small cubes above the rigidbody in question. Oddly enough, they stop above 2.0, 1.0, 0.0 showing that the rigidbody was moved correctly.
//Rigidbody in question
btRigidBody *btPhys;
//First transform
btPhys->translate(btVector3(0.0, -2.0, 0.0));
//Perform -90 degree rotation
btMatrix3x3 orn = btPhys->getWorldTransform().getBasis();
orn *= btMatrix3x3(btQuaternion( btVector3(0, 0, 1), btScalar(degreesToRads(-90))));
btPhys->getWorldTransform().setBasis(orn);
//Perform second transform
btPhys->translate(btVector3(2.0, 0.0, 0.0));
//Print out final position
btTransform trans;
btPhys->getMotionState()->getWorldTransform(trans);
float x, y, z;
x = trans.getOrigin().getX();
y = trans.getOrigin().getY();
z = trans.getOrigin().getZ();
printf("\n\nposition: %f %f %f\n\n", x, y, z);
Basically, I'd just like to be able to get the correct position of the rigidbody from this code (2.0, 1.0, 0.0). Thank you!
In your case, if you want to obtain correct position of btRigidBody you should call:
btPhys->getWorldTransform().getOrigin();
You are calling
btPhys->getMotionState()->getWorldTransform(trans);
instead, but the MotionState is not yet updated. All MotionStates are updated in simulation step.

OpenGL 3D Transformation: z-Aspect ratio

I'm doing 3D perspective projection in OpenGL (webgl), doing it myself with uniform-matrices.
Everthing is working fine, but I have an aspect ration of 3:2 (600px x 400px) and this distorts all geometry rendered.
In 2D I used to fix this in the model matrix by dividing x and y through 1 / width and 1 / height respectively.
Now I also have z to worry about and I am pretty clueless how / where to transform z to not distort on my 3:2 aspect ratio.
The model matrix does not seem to offer any opportunity to do this and I don't know where / what to do in the projection matrix.
Edit:
Projection Matrix:
#_pMatrix = [
1, 0.0, 0.0, 0.0,
0.0, 1, 0.0, 0.0,
0.0, 0.0, -(f + n) / (f - n), -1,
0.0, 0.0, -2.0 * n * f / (f - n), 0.0
]
Column major order
Edit 2:
Weird distortions on n < 1
You're missing the *left*, *right*, *top*, *bottom* in your projection matrix.
2*n
----- 0 0 0
r-l
2*n
0 ----- 0 0
t-b
r+l t+b -(f+n)
----- ----- ------ -1
r-l t-b f-n
-2*f*n 0
0 0 ------
f-n
If you define (r-l)/(t-b) = 3/2 such that the viewing volume is the appropriate size for your model, then you should be set.
Here are some slides describing the various projection matrices and how they're derived:
http://www.cs.unm.edu/~angel/CS433/LECTURES/CS433_17.pdf
They're by Edward Angel, the author of Interactive Computer Graphics, which is where I got this matrix. Unfortunately the OpenGL Red Book doesn't seem to work through the math at all.

Rotation and Translation on Object coordinate

I'm programming a simple application in OpenGL. I have a model that I want to rotate around its center (local coordinate), then translate it along with its local coordinate, too. I've done two scenarios,
rotate then translate, and vice versa. In the first scenario, I got the rotation correct but the model then translate based on the world coordinate not the model (local) coordinate. When I translate first, I got the translation right but the rotation is no longer around the model center.
here's the code,
glPushMatrix();
// ignore this
/*glRotatef(_zRoll, 0.0, 0.0, 1.0);
glRotatef(_yTilt, 1.0, 0.0, 0.0);
glRotatef(_xPan, 0.0, 1.0, 0.0);*/
glScalef(scale, scale, scale);
glTranslatef(0.0, 0.0, -2.0);
glTranslatef(_xTranslate, _yTranslate, _zTranslate); // The required translation
// The required rotation
glRotatef(_yangle, 0.0, 1.0, 0.0);
glRotatef(_zangle, 0.0, 0.0, 1.0);
glRotatef(_xangle, 1.0, 0.0, 0.0);
glTranslatef(coord.x, coord.y, coord.z); // translate to the model center
glCallList(aHelix);
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
glPopMatrix();
glutSwapBuffers();
I think I understand now what you're looking for. I will attempt to restate what you want, so please correct me if I am mistaken.
Let's take a simple model with the following vertex coordinates (columns are vertices):
[3 2 3 4]
[5 2 3 2]
[0 0 0 0]
[1 1 1 1]
So the first point is at x=3, y=5, z=0. Drawing this model we get:
If we simply rotate the model (in this case by 43°) and then translate it in the Y direction (up), say 4 units, we get this:
The model has now moved 4 units in the Y direction, but in the world coordinate frame. As I understand it, the result above is what you DO NOT want.
If instead we translate the model in the direction it is pointing after rotation, we get this:
This, I believe, is what you DO want. Here's the code I used.
glTranslatef(3.0, 3.0, 0.0);
glTranslatef(-2.728, 2.924, 0.0);
glRotatef(43.0, 0.0, 0.0, 1.0);
glTranslatef(-3.0, -3.0, 0.0);
I first rotate the model by 43 degrees and then translate it according to the updated local Y direction. I got the hardcoded translation vector by taking the vector [0 4 0 0] and rotating it using the same 43° rotation matrix I used for the model. This isn't straightforward to do programmatically (at least in the fixed pipeline) and it gets worse with subsequent rotations.
It turns out, though, that you get the exact same results (which you can verify manually) by performing the translation by [0 4 0 0] first, followed by the rotation:
glTranslatef(3.0, 3.0, 0.0);
glRotatef(43.0, 0.0, 0.0, 1.0);
glTranslatef(0.0, 4.0, 0.0);
glTranslatef(-3.0, -3.0, 0.0);
Here's the result of the second set of code for comparison:
The problem is that if you do any subsequent rotations/translations, your coordinate systems still get all messed up. To get around this, you need to make sure you're using an accumulator for your rotations and translations and applying them all at once to the original model rather than making small incremental changes. So, for each press of the up-arrow key, add some incremental value to your _yTranslate variable, for each press of the "rotate" button, add or subtract some value from _zangle, and so on.

OpenGL: How do I get the coordinates of a specific point after transformation?

Suppose I have a point at (250,125,-20).
After the following transformation,
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(100.0, 50.0, 0.0);
glRotatef(-25.0, 0.0, 1.0, 0.0);
How can I get the value of current coordinates of that point?
Need I write a subroutine to multiply a matrix to a vector?
Are there any built-in solutions?
You can't get the coordinates for a specific vertex (point) after a transformation, however for this particular case you can get the ModelViewMatrix after the translate/rotate is applied.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(100.0, 50.0, 0.0);
glRotatef(-25.0, 0.0, 1.0, 0.0);
glGetFloatv(GL_MODELVIEW_MATRIX , *your_matrix*);
//print your matrix to check if that is the desired transformation coordinates
There is no magic tape in OpenGL, you will have to write your own framework e.g: for every objects in your world a class where you hold the vertices and what data you find relevant.

OpenGL ,World to Object coordinate mapping ? (inverse matrix)

Greetings all,
As seen in the image,
I have an object named O (set of linestripes).Its object-coordinate system is (x',y',z').
I translate,rotate this object in my OpenGL scene using following code snippet:
glPushMatrix();
glTranslatef(Oz, Oy,Oz);
glRotatef(rotationX , 1.0, 0.0, 0.0);
glRotatef(rotationY, 0.0, 1.0, 0.0);
glRotatef(rotationZ, 0.0, 0.0, 1.0);
contour->render();
glPopMatrix()
;
I have a point called H ,which is translated to (hx,hy,hz) world coordinates using
glPushMatrix();
glTranslatef(hx,hy,hz);
glPopMatrix();
If I am correct, (Oz,Oy,Oz) and (hx,hy,hz) are world coordinates.
Now,what I want todo is calculate the position of H (hx,hy,hz) relative to O's object-coordinate system.(x',y',z');
As I understood,I can do this by calculating inverse transformations of object O and apply them to point H.
Any tips on this? Does OpenGL gives any functions for inverse-matrix calculation ? If I somehow found inverse-matrices what the order of multiplying them ?
Note : I want to implement "hammer" like tool where at point H ,I draw a sphere with radius R.User can use this sphere to chop the object O like a hammer.I have implemented this in 2D ,so I can use the same algorithm if I can calculate the hammer position
relative to (x',y',z')
Thanks in advance.
Inverting the matrix would be the general solution, but as far as I can see this isn't actually a "general" problem. Rather than undoing an arbitrary transformation, you are trying to do the reverse of a known sequence of transformations, each of which can be inverted very simply. If your object-to-world transformation is:
glTranslatef(Ox, Oy, Oz);
glRotatef(rotationX , 1.0, 0.0, 0.0);
glRotatef(rotationY, 0.0, 1.0, 0.0);
glRotatef(rotationZ, 0.0, 0.0, 1.0);
Then the world-to-object inverse is just:
glRotatef(-rotationZ, 0.0, 0.0, 1.0);
glRotatef(-rotationY, 0.0, 1.0, 0.0);
glRotatef(-rotationX , 1.0, 0.0, 0.0);
glTranslatef(-Ox, -Oy, -Oz);
Basically, just back out each applied transformation in the opposite order originally applied.
Yes, basically you're right that you can perform this operation by the translation matrix
M = O^-1 * H
any like you already guessed you need the inverse of O for this. OpenGL is not a math library though, it only deals with rendering stuff. So you'll have to implement the inversion yourself. Google for "Gauss Jordan" to find one possible algorithm. If you can be absolutely sure, that O consists only of rotation and translation, i.e. no shearing or scaling, then you can shortcut by transposing the upper left 3x3 submatrix and negating the uppermost 3 elements of the rightmost column (this exploits the nature of orthogonal matrices, like rotation matrices, that the transpose is also the inverse, the upper left 3x3 is the rotational part, the inverse of a translation is negating the elements of it's vector which is the rightmost upper 3 elements).