Quaternion rotation matrix unexpectedly has the opposite sense - math

I have some understanding problem concerning quaternions.
In order to have my world object rotate in the correct way, I need to invert their quaternion rotation while refreshing the object world matrix.
I create the object rotation with this code:
Rotation = Quaternion.RotationMatrix(
Matrix.LookAtRH(Position,
Position + new Vector3(_moveDirection.X, 0, _moveDirection.Y),
Vector3.Up)
);
and refresh the object World matrix like this:
Object.World = Matrix.RotationQuaternion(Rotation)
* Matrix.Translation(Position);
This is not working; it makes the object rotate in the opposite way compared to what it should!
The is the way that makes my object rotate correctly:
Object.World = Matrix.RotationQuaternion(Quaternion.invert(Rotation))
* Matrix.Translation(Position);
Why do I have to invert the object rotation?

This isn't a quaternion problem so much as it is a usage and/or documentation issue with the DirectX call you're using. The transformation the call gives is the one that happens when you move the camera. If you're keeping the camera fixed and moving the world, you're swapping what's moving and what's fixed. These coordinate transformations are inverses of each other, which is why taking the inverse works for you.
You don't need to take an explicit inverse, though. Just swap the order of the first two arguments.

Related

How to decompose a unknown transformation matrix?

I'm working in the revitalization of an old 3d game (built using Direct3D) and I'm struggling with the game objects animations.
The game has its objects animations stored in binary files that contains transformation matrices for each bone of its meshes at each frame of the animation (in the form of an array of D3DMATRIX).
I've tried using the D3DXMatrixDecompose function to get the position, rotation and scale but it seems that something is wrong with the animation. Some animations almost matches the originals, but there are some strange rotations in the middle of the animations (the scale vector goes from negative to positive values and that causes the whole bone to rotate in an strange way - it is definitely wrong) and for other animations the whole thing is wrong.
I read somewhere that the function D3DXMatrixDecompose assumes the matrix was composed as a SRT matrix and apparently the order in which each component was combined in the matrix matters. So, as the animations are clearly wrong I'm assuming maybe the matrices were not composed in the SRT order and the output of D3DXMatrixDecompose is wrong.
I didn't find much material to read about this without going very deep on math. As I don't have a strong background on math, hopefully someone can point me in the right direction.
So, how can I decompose position, rotation and scale of an unknown transformation matrix? I'm not asking for a unique algorithm that can do that, I'm asking what I can do in this scenario to find the original (or equivalents) values for the position, rotation and scale of each matrix.
Thanks in advance!

Is there an algorithm to apply a rotation onto Euler angles?

I'm working on some local space functions for a little project.
I've got a function called getRotation(), which should return the euler angles for an object given it's parent's rotation and it's own local rotation.
So given two rotation vectors:
Vector3f parentRotation
Vector3f localRotation
How can I apply the local rotation onto the parent rotation?
If it helps I'm using Java with LWJGL 2.
The solution here was to move to a a transformation matrix as suggested by Spektre.
While this may be possible with Vector3f angles, those just aren't suitable for game development, at least not with this stack, as they introduce many problems.

What is the difference between Rotation and getComponentRotation?

In the UE4 game engine
What is the difference between Rotation and GetComponentRotation?
Try to understand this by documentation on at
https://api.unrealengine.com/INT/API/Runtime/Core/Math/FVector/Rotation/index.html
But I could not?
I need some details and explanation about this ..
These two methods are from different objects:
FVector::Rotation
USceneComponent::GetComponentRotation
Both return a rotation object (FRotator) that encodes the rotation in the Yaw/Pitch/Roll representation.
The difference is that the Rotation returns an FRotator object that, if applied to a component, will make the component "look" in the direction of the vector. For example, if you take the difference between the position of a sphere and the position of a player, use Rotation, and then apply the rotation to the player, the player will face the sphere.
GetComponentRotation returns the current orientation of the component in global space.

Calculating modelview matrix for 2D camera using Eigen

I'm trying to calculate modelview matrix of my 2D camera but I can't get the formula right. I use the Affine3f transform class so the matrix is compatible with OpenGL. This is closest that I did get by trial and error. This code rotates and scales the camera ok, but if I apply translation and rotation at same time the camera movement gets messed up: camera moves in rotated fashion, which is not what I want. (And this probaly due to fact I first apply the rotation matrix and then translation)
Eigen::Affine3f modelview;
modelview.setIdentity();
modelview.translate(Eigen::Vector3f(camera_offset_x, camera_offset_y, 0.0f));
modelview.scale(Eigen::Vector3f(camera_zoom_x, camera_zoom_y, 0.0f));
modelview.rotate(Eigen::AngleAxisf(camera_angle, Eigen::Vector3f::UnitZ()));
modelview.translate(Eigen::Vector3f(camera_x, camera_y, 0.0f));
[loadmatrix_to_gl]
What I want is that camera would rotate and scale around offset position in screenspace {(0,0) is middle of the screen in this case} and then be positioned along the global xy-axes in worldspace {(0,0) is also initialy at middle of the screen} to the final position. How would I do this?
Note that I have set up also an orthographic projection matrix, which may affect this problem.
If you want a 2D image, rendered in the XY plane with OpenGL, to (1) rotate counter-clockwise by a around point P, (2) scale by S, and then (3) translate so that pixels at C (in the newly scaled and rotated image) are at the origin, you would use this transformation:
translate by -P (this moves the pixels at P to the origin)
rotate by a
translate by P (this moves the origin back to where it was)
scale by S (if you did this earlier, your rotation would be messed up)
translate by -C
If the 2D image we being rendered at the origin, you'd also need to end by translate by some value along the negative z axis to be able to see it.
Normally, you'd just do this with OpenGL basics (glTranslatef, glScalef, glRotatef, etc.). And you would do them in the reverse order that I've listed them. Since you want to use glLoadMatrix, you'd do things in the order I described with Eigen. It's important to remember that OpenGL is expecting a Column Major matrix (but that seems to be the default for Eigen; so that's probably not a problem).
JCooper did great explaining the steps to construct the initial matrix.
However I eventually solved the problem bit differently. There was few additional things and steps that were not obvious for me at the time. See JCooper answer's comments. First is to realize all matrix operations are relative.
Thus if you want to position or move the camera with absolute xy-axes, you must first decompose the matrix to extract its absolute position with unchanged axes. Then you translate the matrix by the difference of the old and new position.
Here is way to do this with Eigen:
First compute Affine2f matrix cmat scalar determinant D. With Eigen this is done with D = cmat.linear().determinant();. Next compute 'reverse' matrix matrev of the current rotation+scale matrix R using the D. matrev = (RS.array() / (1.0f / determ)).matrix()); where RS is cmat.matrix().topLeftCorner(2,2)
The absolute camera position P is then given by P = invmat * -C where C is cmat.matrix().col(2).head<2>()
Now we can reposition the camera anywhere along the absolute axes and keeping the rotation+scaling same: V = RS * (T - P) where RS is same as before, T is the new position vec and P is the decomposed position vec.
The cmat then simply translated by V to move the camera: cmat.pretranslate(V)

Help me with Rigid Body Physics/Transformations

I want to instance a slider constraint, that allows a body to slide between point A and point B.
To instance the constraint, I assign the two bodies to constrain, in this case, one dynamic body constrained to the static world, think sliding door.
The third and fourth parameters are transformations, reference Frame A and reference Frame B.
To create and manipulate Transformations, the library supports Quaternions, Matrices and Euler angles.
The default slider constraint slides the body along the x-axis.
My question is:
How do I set up the two transformations, so that Body B slides along an axis given by its own origin and an additional point in space?
Naively I tried:
frameA.setOrigin(origin_of_point); //since the world itself has origin (0,0,0)
frameA.setRotation(Quaternion(directionToB, 0 rotation));
frameB.setOrigin(0,0,0); //axis goes through origin of object
frameB.setRotation(Quaternion(directionToPoint,0))
However, Quaternions don't seem to work as I expected. My mathematical knowledge of them is not good, so if someone could fill me in on why this doesn't work, I'd be grateful.
What happens is that the body slides along an axis orthogonal to the direction. When I vary the rotational part in the Quaternion constructor, the body is rotated around that sliding direction.
Edit:
The framework is bullet physics.
The two transformations are how the slider joint is attached at each body in respect to each body's local coordinate system.
Edit2
I could also set the transformations' rotational parts through a orthogonal basis, but then I'd have to reliably construct a orthogonal basis from a single vector. I hoped quaternions would prevent this.
Edit3
I'm having some limited success with the following procedure:
btTransform trafoA, trafoB;
trafoA.setIdentity();
trafoB.setIdentity();
vec3 bodyorigin(entA->getTrafo().col_t);
vec3 thisorigin(trafo.col_t);
vec3 dir=bodyorigin-thisorigin;
dir.Normalize();
mat4x4 dg=dgGrammSchmidt(dir);
mat4x4 dg2=dgGrammSchmidt(-dir);
btMatrix3x3 m(
dg.col_x.x, dg.col_y.x, dg.col_z.x,
dg.col_x.y, dg.col_y.y, dg.col_z.y,
dg.col_x.z, dg.col_y.z, dg.col_z.z);
btMatrix3x3 m2(
dg2.col_x.x, dg2.col_y.x, dg2.col_z.x,
dg2.col_x.y, dg2.col_y.y, dg2.col_z.y,
dg2.col_x.z, dg2.col_y.z, dg2.col_z.z);
trafoA.setBasis(m);
trafoB.setBasis(m2);
trafoA.setOrigin(btVector3(trafo.col_t.x,trafo.col_t.y,trafo.col_t.z));
btSliderConstraint* sc=new btSliderConstraint(*game.worldBody, *entA->getBody(), trafoA, trafoB, true);
However, the GramSchmidt always flips some axes of the trafoB matrix and the door appears upside down or right to left.
I was hoping for a more elegant way to solve this.
Edit4
I found a solution, but I'm not sure whether this will cause a singularity in the constraint solver if the top vector aligns with the sliding direction:
btTransform rbat = rba->getCenterOfMassTransform();
btVector3 up(rbat.getBasis()[0][0], rbat.getBasis()[1][0], rbat.getBasis()[2][0]);
btVector3 direction = (rbb->getWorldTransform().getOrigin() - btVector3(trafo.col_t.x, trafo.col_t.y, trafo.col_t.z)).normalize();
btScalar angle = acos(up.dot(direction));
btVector3 axis = up.cross(direction);
trafoA.setRotation(btQuaternion(axis, angle));
trafoB.setRotation(btQuaternion(axis, angle));
trafoA.setOrigin(btVector3(trafo.col_t.x,trafo.col_t.y,trafo.col_t.z));
Is it possible you're making this way too complicated? It sounds like a simple parametric translation (x = p*A+(1-p)*B) would do it. The whole rotation / orientation thing is a red herring if your sliding-door analogy is accurate.
If, on the other hand, you're trying to constrain to an interpolation between two orientations, you'll need to set additional limits 'cause there is no unique solution in the general case.
-- MarkusQ
It would help if you could say what framework or API you're using, or copy and paste the documentation for the function you're calling. Without that kind of detail I can only guess:
Background: a quaternion represents a 3-dimensional rotation combined with a scale. (Usually you don't want the complications involved in managing the scale, so you work with unit quaternions representing rotations only.) Matrices and Euler angles are two alternative ways of representing rotations.
A frame of reference is a position plus a rotation. Think of an object placed at a position in space and then rotated to face in a particular direction.
So frame A probably needs to be the initial position and rotation of the object (when the slider is at one end), and frame B the final position and rotation of the object (when the slider is at the other end). In particular, the two rotations probably ought to be the same, since you want the object to slide rigidly.
But as I say, this is just a guess.
Update: is this Bullet Physics? It doesn't seem to have much in the way of documentation, does it?
Perhaps you are looking for slerp?
Slerp is shorthand for spherical
linear interpolation, introduced by
Ken Shoemake in the context of
quaternion interpolation for the
purpose of animating 3D rotation. It
refers to constant speed motion along
a unit radius great circle arc, given
the ends and an interpolation
parameter between 0 and 1.
At the end of the day, you still need the traditional rotational matrix to get things rotated.
Edit: So, I am still guessing, but I assume that the framework takes care of the slerping and you want the two transformations which describes begin state and the end state?
You can stack affine transformations on top of the other. Except you have to think backwards. For example, let's say the sliding door is placed at (1, 1, 1) facing east at the begin state and you want to slide it towards north by (0, 1, 0). The door would end up at (1, 1, 1) + (0, 1, 0).
For begin state, rotate the door towards east. Then on top of that you apply another translation matrix to move the door to (1, 1, 1). For end state, again, you rotate the door towards east, then you move the door to (1, 1, 1) by applying the translation matrix again. Next, you apply the translation matrix (0, 1, 0).

Resources