How to flip only one axis of transformation matrix? - opengl

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.

Related

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 :)

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

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.

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.

How to get maya like rotations?

I am trying to achieve the same rotational effect like Maya in my project.
I have some knowledge on quaternions and the trackball example.
Unfortunately I am still unable to wrap my head around the concept of using the quaternions to get the desired effect.
Basically I am still getting the same issue I had before with the 3d trackball. After flipping the object upside down, and then trying to rotate to the right, the object will rotate to the left. Well actually its my camera rotating around the focus point in the opposite direction.
The problem is that I am using the screen coordinates & trackball to get the old / new vectors and getting the angle of rotation from those two vectors. I will always get the wrong axis of rotation this way.
How should I go about solving this issue?
I don't know Maya so I can only guess that its rotation is like this: if you rotate left-right, it feels natural. Then if you rotate the object up-down 180 degrees, then rotate left-right again, it still feels natural.
If you are familiar with the concept of using a matrix to do transformations (like rotate, scale and translate), well a quaternion is just the same concept but it only allows rotations, so you might want to use it to constrain your transforms to just rotations. In practice, you can use either a matrix or a quaternion to do the same thing.
What you need to do is remember the current quaternion state for the object, then when the next frame of rotation occurs, multiply the new rotation with the old quaternion (in that order) to give you the next frame's quaternion. That will ensure that no matter what orientation the object is in, the next frame's rotation will be applied from the viewer's viewpoint. This is as opposed to some naive rotation where you just say "user is scrolling up/down, therefore alter the object's X-axis rotation", which causes that flipping.
Remember, like matrices, quaternions need to be multiplied in reverse order that the actions are actually applied, which is why I said to multiply the new operation by the existing quaternion.
To finish with an example. Let's say the user is going to perform 2 actions:
On frame 1, the user rotates the object 180 degrees about the X axis (up/down rotation).
On frame 2, the user rotates the object 90 degrees about the Y axis (left/right rotation).
Lets say the object has a quaternion Q. Every frame, you will reset the object to its default coordinates and apply the quaternion Q to rotate it. Now you might initialise it with the identity quaternion, but let's just say the initial quaternion is called Q0.
On frame 1, create a new quaternion R1 which is a "rotate 180 degrees about the X axis" quaternion (you can find some maths to compute such a quaternion). Pre-multiply the new operation by the existing quaternion: Q1 = R1 * Q0.
On frame 2, create a new quaternion R2 which is a "rotate 90 degrees about the Y axis" quaternion. Pre-multiply the new operation by the existing quaternion: Q2 = R2 * Q1.
On frame 1 you will use Q1 to display the object, and on frame 2 you will use Q2. You can simply keep applying any subsequent user actions to the quaternion and it will always be rotated in the viewer's frame of reference.
I think you have problems with changing coordinate system.
Suppose, you want to rotate object in X Axis, then in Y Axis, and then move it and scale. So, you should multiply your transformation maxtrix (at the beginning it equals to itentity matrix) to the rotation matrix (firstly to X, then to Y), then to translation matrix and at the end to scaling matrix. So, when your current matrix multiplies to the resulting matrix, your coordinate systems changes.
To avoid this problem you can use 2 methods:
1) to accumulate your resultig matrix as product of all previous matrices.
2) to use stack, where in the top will be the matrix, which equals to product of all matrices in the bottom of this matrix (in the stack).
P.S. I'm not sure, that it helps you. I never used quaternions in my projects.

Translating a Quaternion

(perhaps this is better for a math Stack Exchange?)
I have a chain composed of bones. Each bone has a with a tip and tail. The following code computes where its tip will be, given a rotation, and sets the next link in the chain's position appropriately:
// Quaternion is a hand-rolled class that works correctly (as far as I can tell.)
Quaternion quat = new Quaternion(getRotationAngleDegrees(), getRotation());
// figure out where the tip will be after applying the rotation
Vector3f rotatedTip = quat.applyRotationTo(tip);
// set the next bone's tail to be at this one's tip
updateNextPosFrom(rotatedTip);
This works if the rotation is supposed to occur around the origin of the object's coordinate system. But what if I want the rotation to occur around some other arbitrary point in the object? I'm not sure how to translate the quaternion. What is the best way to do it?
(I'm using JOGL / OpenGL.)
Dual quaternions are useful for expressing rigid spatial transformations (combined rotations and translations.)
Based on dual numbers (one of the Clifford algebras, d = a + e b where a, b are real and e is unequal to zero but e^2 = 0), dual quaternions, U + e V, can represent lines in space with U the unit direction quaternion and V the moment about a reference point. In this way, dual quaternion lines are very much like Pluecker lines.
While the quaternion transform Q V Q* (Q* is the quaternion conjugate of Q) is used to rotate a unit vector quaternion V about a point, a similar dual quaternion form can be used to apply to line a screw transform (the rigid rotation about an axis combined with a translation along the axis.)
Just as any rigid 2D transform can be resolved to a rotation about a point, any rigid 3D transform can be resolved to a screw.
For such power and expressiveness, dual quaternion references are thin, and the Wikipedia article is as good a place as any to start.
A quaternion is used specifically to handle a rotation factor, but does not include a translation at all.
Typically, in this situation, you'll want to apply a rotation to a point based on the "bone's" length, but centered at the origin. You can then translate post-rotation to the proper location in space.
Quaternions are generally used to represent rotations only; they cannot represent translations as well.
You need to convert your quaternion into a rotation matrix, insert it into the appropriate part of your standard OpenGL 4x4 matrix, and combine it with a translation in order to rotate about an arbitrary point.
4x4 rotation matrix:
[ r r r 0 ]
[ r r r 0 ] <- the r's are the 3x3 rotation matrix from the wiki article
[ r r r 0 ]
[ 0 0 0 1 ]
The Wikipedia page on forward kinematics points to this paper: Introduction to Homogeneous Transformations & Robot Kinematics.
Edit : This answer is wrong. It argues on 4x4 transformation matrices properties, which are not quaternions...
I might have got it wrong but to me (unlike some answers) a quaternion is indeed a tool to handle rotations and translations (and more). It is a 4x4 matrix where the last column represents the translation. Using matrix algebra, replace the 3-vector (x, y, z) by the 4-vector (x, y, z, 1) and compute the transformed vector by the matrix. You will find that values of the last column of the matrix will be added to the coordinates x, y, z of the original vector, as in a translation.
A 3x3 matrix for a 3D space represents a linear transformation (like rotation around the origin). You cannot use a 3x3 matrix for an affine transformation like a translation. So I understand simply the quaternions as a little "trick" to represent more kinds of transformations using matrix algebra. The trick is to add a fourth coordinate equal to 1 and to use 4x4 matrices. Because matrix algebra remains valid, you can combine space transformations by multiplying the matrices, which is indeed powerful.