Matrix multiplication to mirror translation and rotation of only 1 axis? - opengl

I'm using OpenGL with some other library. This library will provide Projection Matrix and I cannot modify it. I have to provide only ModelViewMatrix.
However, strange things happen. Only y-axis translation and rotation are inverted.
For example if I increase x translation in the ModelViewMatrix then the object will go to the right just fine. (positive x direction) but in y-axis it is reversed. I want it to go the other way.
Rotation in y-axis also got reversed. It is rotation opposite of the way it should be.
I cannot fix it on ProjectionMatrix, so I think I might have to multiply my ModelViewMatrix with something that can reverse one axis before send it to the library. Do you know that something? A matrix that can reverse 1 axis?

it's just a matrix with elements [1,0,0,0][0,-1,0,0][0,0,1,0][0,0,0,1]
in other words an identity matrix with the second diagonal element negated.

Related

How to calculate a linear tapering transformation matrix

I need to calculate a 4x4 matrix (for OpenGL) that can transform a 3d object on the left to one on the right. Transformation applied only in one axis.
EDIT:
The inputs are a given 3d object (points) to be deformed and a single variable for the amount of deformation.
A picture represents a cube projected to plane showing only relevant changes. There are no changes in the axis perpendicular to view plane.
The relative position of these two objects is not relevant and used only to show "before and after" situation.
******* wrong answer was here *******
It's somewhat opposite to 2D perspective matrix with further perspective division. So, to do this "perspective" thing inversely, you need to do something opposite to perspective division then multiply the result by an inverted "perspective" matrix. And though the perspective matrix may be inverted, I have no idea what is "opposite to perspective division". I think you just can't do it with matrices. You'll have to transform Y coord of each vertex instead

OpenCV -SolvePNP how to compute guess from world coords

For cv::SolvePNP, I would like to provide an initial guess for translation and rotation.
For the guess, I have the translation in world space and the rotation as up and direction vector (or Euler angles).
How do we transform the world space translation and up/direction vector to the correct format so cv:: SolvePNP can use it as as proper guess in the correct coordinate system?
I use useExtrinsicGuess=true, and provide tvec and rvec.
I computed a rotation matrix from the up and direction vectors, though there seems to be different conventions.
And then convert the rotation matrix with Rodrigues to rvec.
We use
Tvec=-R*worldspace_tvec.
However, the results are clearly not right as the guess places the resulting tvec and rvec in a different place once converting it back to Euler/world space translation.
Is there a fast way to go from up/direction vectors and world space translations to the correct tvec and rvec inputs for SolvePNP?
Thanks in advance.

How to flip only one axis of transformation matrix?

I have a 4x4 transformation matrix. However, after trying out the transformation I noticed that movement and rotation of the Y axis is going the opposite way. The rest is correct.
I got this matrix from some other API so probably it is the difference of coordinate system. So, how can I flip an axis of transformation matrix?
If only translation I can add minus sign on the Y translation, but I have no idea about opposite rotation of only one axis since all the rotation is being represented in the same 3x3 area. I thought there might be some way that even affect both translation and rotation at the same time. (truly flipping the axis)
Edit: I'm pretty sure the operation you're looking for is changing coordinate systems while maintaining Z-up or Y-up. In this case, try setting all the elements of the second column (or row) of your matrix to their inverse.
This question would be better for the Math StackExchange. First, a really helpful read on rotation matrices.
The first problem is the matter of rotation order. I will be assuming the XYZ rotation order. We know the rotation matrices for each axis is as follows:
Given a matrix derived from the same rotation order, the resulting matrix would be as follows, where alpha is the X angle, beta is the Y angle, and gamma is the Z angle:
You can derive the individual components of each axis angle from this matrix. For example, you can derive the Y angle from -sin(beta) using some inverse trig. Given beta, you can derive alpha from cos(beta)sin(alpha). You can also derive gamma from cos(beta)sin(gamma). Note that the same number in the matrix can represent multiple values (e.g. sin(0)=0 and sin(180)=0).
Now that you know alpha, beta, and gamma, you can reverse beta and remake the rotation matrix.
There's a good chance that there's a better way to do this using quaternions, but you should ask the Math StackExchange these kinds of language-agnostic questions.
Much shorter answer: if you are not careful with your frame orientation many things down your pipeline are likely to have a bad hair day. The reason is "parity", a.k.a. "frame orientation", a.k.a. "right-handedness" (or rarely left-handedness). Most 3D geometry tools and libraries that work together normally assume implicitly that all coordinate systems in play are right-handed (or at least consistently-handed). Inverting the orientation of just one axis in a coordinate system changes its orientation from right to left handed or viceversa.
So, suggestion for things to check & try in your problem:
Check that the frame you get from your API is right-handed. You do so
by computing the determinant of the 3x3 rotation part of your 4x4 transform matrix: it must be +1 or very close to it.
If it is -1, then flip one if its axis, i.e. change the sign of one of the columns of the 3x3 rotation.
Note carefully: I said "columns" because I assume that you apply a transform Q to a point x by multiplying as Q * x, x being a 4x1 column vector with the last component equal to one. If you use row vectors left-multiplied by Q you need flip a row.
If that determinant is +1, you have a bug someplace else.

Rotating object along all 3 axes to map to the player's camera LookAt vector

I have a simple 3D LookAt vector, and I wish to rotate the player model (a simple cube) to show where the player/cube is looking at.
For sideways camera movement I've managed to figure it out and do the following:
glTranslatef(position.x, position.y, position.z);
glRotatef(atan2(lookAt.z, lookAt.x) * 180 / PI, 0, 1, 0);
Now I know that to get up-down camera movement to map to the rendered cube model, I need to rotate the cube around it's x and z axes as well, but I can't seem to figure out what formula to use for those two.
OpenGL will rotate the whole coordinate system (whole space, not only a cube) so after first rotation you just need to rotate only around z axis.
// first rotation
glRotatef(-atan2(lookAt.z, lookAt.x) * 180 / PI, 0, 1, 0);
// second rotation
float d = sqrt(pow(lookAt.x,2) + pow(lookAt.z,2));
float pitch = atan2(lookAt.y, d);
glRotatef(pitch * 180 / PI, 0, 0, 1);
First and second rotation:
I assume your model is looking along x axis (red arrow). I also assume lookAt is given relative to the position of the model.
If you're familiar with matrix math, matrices are an easier way to think about it. If you're not familiar with matrices, this series explains how to use them to solve common game development problems: https://www.youtube.com/playlist?list=PLW3Zl3wyJwWNQjMz941uyOIq3Nw6bcDYC Getting good with matrices is a good idea if you want to be a 3D game programmer.
For your problem, you want to make a translation/rotation matrix which will transform the box to the proper place for you. You can make a translation matrix and a rotation matrix individually, and then at the end take the product of the two. I'll try to break that down.
The translation matrix is simple, if your position is then your matrix will be
To construct a rotation matrix, you need to rotate the standard basis vectors the way you want. Then when you create a matrix from those rotated basis vectors, the matrix will rotate other vectors in the same way. As an example of that, take the standard basis vectors:
Now I'm going to rotate and around by 90 degrees clockwise:
Now put them into a matrix:
and you have R is a matrix that rotates things around by 90 degrees.
In your case you want to rotate stuff such that it faces a vector that you provide. That makes things easy, we can calculate our basis vectors from that vector. If your vector is then and we can solve for the other two basis vectors using cross products. You know that the character won't ever roll their view (right?) so we can use the global up vector as well. I'll call the global up vector . In your case you're using y as the "up" dimension so the global up vector will be
Then:
In the first line you do a cross product between the view vector and the up vector to get a vector orthogonal to both - this will serve as the third basis vector after it is normalized, which is the second line. In the third line another cross product generates the second basis vector. These three vectors represent what happens when the standard basis vectors are rotated the way you want them to be. Use them as the columns in a matrix like so:
Now the last step in the math is to make a final matrix that will do both translation and rotation, and this step is easy:
Then load that matrix into OpenGL with glLoadMatrix:
glLoadMatrixf(&M);
All of this gets explained in the video series I linked as well :)

How to know that object has been rotated only in 15 degree chunks in 3D?

I have an 3D object in 3D space oriented in some orientation. How can I know it has been rotated from its initial rotation q (in euler angles: 0, 0, 0) only in arbitrary number of 15 degree rotations in any axis. E.g, rotated in X-axis 4*15 degrees, and in Y-axis 7*15 degrees and in Z-axis 13*15 degrees. How can I detect this?
I have tried to take euler angles from the object's rotation matrix but it seems to detect the situation correctly only if I rotate only in one axis. If I start to mix X,Y and Z axis 15 degree rotations, the euler angles gets messed up.
I am 100% sure that the object has been rotated only in 15 degree chunks.
Rotation matrices can only be decomposed into quaternions, I believe, and cannot be decomposed into per-axis rotations.
I am not sure what math library you are using, but, if provided, you could use quaternions, which will quite straightforward the functionality you want. They can be translated to rotation matrices afterwards.
Rotations are not commutative, therefore describing them with Euler angles is problematic if you don't know the right order. If you know the order, you can set up an equation system with a multiplication of three rotation matrices (parameterized by the rotation angle) on one side and the final rotation matrix on the other side. Gives you three equations and three unknowns. But watch out for singularities in Euler angle representation!
If you can, the dead simplest way is to store both the components (float3 m_Translation, m_Rotation, m_Scale) and a matrix that is updated whenever they change (float4x4 m_Matrix). To get the data out, simply grab the vector for that part and return it. The memory use is small (12-16 floats) and computational overhead is minimal (recalculate the matrix when a part is updated).
However, if that can't be done, Google suggests you can decompose rotation matrices with a bit of work like so. It does take a chunk of math.
As noted in that page, the D3DX libraries also have a function to decompose matrices: D3DXMatrixDecompose.