How to convert a Eigen::Quaternion<float> to a Matrix4f? - c++

As the title says, i have a problem to convert a Quaternion to a Matrix4f. Eigen has the method Quaternion.toRotationMatrix() which gives me a Matrix3f.
Now i need a Matrix4f ( because our program is designed to take only Matrix4f), is there an easy way to achieve this?

#Zacharias' answer contains the necessary theory. I just reiterate my earlier comment I made there with the actual Eigen C++ code.
Eigen::Matrix3f mat3 = Eigen::Quaternionf(W, X, Y, Z).toRotationMatrix();
Eigen::Matrix4f mat4 = Eigen::Matrix4f::Identity();
mat4.block(0,0,3,3) = mat3;
Eigen::Matrix4f::Identity() takes care of initializing the ones and zeros of the 4th and last row and column. mat4.block(0,0,3,3) = mat3 then overwrites the values obtained from the rotation matrix.

M3 to M4
The answere is already there, given by Rob and Najzero.
In most cases, it will be sufficient to construct the matrix as follows:
m3:
|a00|a01|a02|
|a10|a11|a12|
|a20|a21|a22|
to m4:
|a00|a01|a02| 0 |
|a10|a11|a12| 0 |
|a20|a21|a22| 0 |
| 0 | 0 | 0 | 1 |
The 4x4 matrix does not only allow to rotate a vector, but also to shift(translate) and scale (in all 3 directions) any vector. So basically you got a full transformation matrix - thats why it is often used in computer graphics, describing the transformation of an object. Depending on row-column order, we might identify the matrix as:
|rot|rot|rot| sx |
|rot|rot|rot| sy |
|rot|rot|rot| sz |
| x | y | z | 1 |
with sx,sy,sz as scaling coefficients, and x,y,z as translation coefficients.
PS: of course, if you want to rotate a vector with m4, you will than have to use a 4-dimensional vector, e.g. (x,y,z,w) with w=1 (in most cases).
The direct approach
Convert Quaternion rotation to rotation matrix?
And my personal recommendation:
http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToMatrix/
There you will find also other transformations, backtrafos and so on.

Related

which coordinate system the normal vector calculated from height map in?

I have read a lot of material about heightmap and normal map, and have many questions:
We can generate a normal map from heightmap:
If we have in the S and T direction:
S(i,j)= <1,0,aH(i+1,j)−aH(i−1,j)>
T(i,j)= <0,1,aH(i,j+1)−aH(i,j−1)>
then we can calculate normal value N:
N(i,j)= (S(i,j) x T(i,j))normalize()
then we map (Nx,Ny,Nz) to (r,g,b) this is the method we use to generate normal map from heightmap.
I tried this with several heightmap and diffuse map(convert the diffuse to grayscale as heightmap). Simple ones can provide relative good normal map. Once the image gets more complex, the result is very bad.
My questions are:
Which coordinate system is this normal vector in?
I feel it is just at the surface of the object and points out to the normal. Is this the so-called 'TBN' space?
But there's no T and B information occurred here.
If t is the tangent space, then for different triangles, we will have different t, so different triangle would have a different T/B/N vector?
How do I calculate TBN from normal map? I'm a little confused reading the book and look at this matrix:
s1,t1 = < s1 − s0,t1 − t0 >
s2,t2 = < s2 − s0,t2 − t0 >
| Tx Ty Tz | | s1 t1 | | Q1x Q1y Q1z |
| Bx By Bz | = inverse of | s2 t2 | | Q2x Q2y Q2z |
What does this s2 and s1 stands for, I know (Q1x Q1y Q1z), are they the (x,y,z) also (r,g,b) value from the normal map, does s2 and s1 stands for the (x,y) location, the pixel location on the normal map?

Explanation of the Perspective Projection Matrix (Second row)

I try to figure out how the Perspective Projection Matrix works.
According to this: https://www.opengl.org/sdk/docs/man2/xhtml/gluPerspective.xml
f = cotangent(fovy/2)
Logically I understand how it works (x- and y-Values moving further away from the bounding box or vice versa), but I need an mathematical explanation why this works. Maybe because of the theorem of intersecting lines???
I found an explanation here: http://www.songho.ca/opengl/gl_projectionmatrix.html
But I don't understand the relevent part of it.
As for me, an explanation of the perspective projection matrix at songho.ca is the best one.
I'll try to retell the main idea, without going into details. But, first of all, let's clarify why the cotangent is used in OpenGL docs.
What is cotangent? Accordingly to wikipedia:
The cotangent of an angle is the ratio of the length of the adjacent side to the length of the opposite side.
Look at the picture below, the near is the length of the adjacent side and the top is the length of the opposite side .
The fov/2 is the angle we are interested in.
The angle fov is the angle between the top plane and bottom plane, respectively the angle fov/2 is the angle between top(or botton) plane and the symmetry axis.
So, the [1,1] element of projection matrix that is defined as cotangent(fovy/2) in opengl docs is equivalent to the ratio near/top.
Let's have a look at the point A specified at the picture. Let's find the y' coordinate of the point A' that is a projection of the point A on the near plane.
Using the ratio of similar triangles, the following relation can be inferred:
y' / near = y / -z
Or:
y' = near * y / -z
The y coordinate in normalized device coordinates can be obtained by dividing by the value top (the range (-top, top) is mapped to the range (-1.0,1.0)), so:
yndc = near / top * y / -z
The coefficient near / top is a constant, but what about z? There is one very important detail about normalized device coordinates.
The output of the vertex shader is a four component vector, that is transformed to three component vector in the interpolator by dividing first three component by the fourth component:
,
So, we can assign to the fourth component the value of -z. It can be done by assigning to the element [2,3] of the projection matrix the value -1.
Similar reasoning can be done for the x coordinate.
We have found the following elements of projection matrix:
| near / right 0 0 0 |
| 0 near / top 0 0 |
| 0 0 ? ? |
| 0 0 -1 0 |
There are two elements that we didn't found, they are marked with '?'.
To make things clear, let's project an arbitary point (x,y,z) to normalized device coordinates:
| near / right 0 0 0 | | x |
| 0 near / top 0 0 | X | y | =
| 0 0 ? ? | | z |
| 0 0 -1 0 | | 1 |
| near / right * x |
= | near / top * y |
| ? |
| -z |
And finally, after dividing by the w component we will get:
| - near / right * x / z |
| - near / top * y / z |
| ? |
Note, that the result matches the equation inferred earlier.
As for the third component that marked with '?'. More complex reasoning is needed to find out how to calculate it. Refer to the songho.ca for more information.
I hope that my explanations make things a bit more clear.

How to find correct rotation from one vector to another?

I have two objects, and each object has two vectors:
normal vector
up vector
Like on this image:
Up vector is perpendicular to normal vector. Now I want to find unique rotation from one object to another, how to do that?
I have one method to find rotation between one vector to another, and it works. The problem is that I need to take care the two vectors: normal vector and up vector. If I use this method to rotate normal vector from object one to normal from object two, the up vector could be pointing wrong way, and they needs to be parallel.
Here is the code for finding the shortest rotation:
GE::Quat GE::Quat::fromTo(const Vector3 &v1, const Vector3 &v2)
{
Vector3 a = Vector3::cross(v1, v2);
Quat q;
float dot = Vector3::dot(v1, v2);
if ( dot >= 1 )
{
q = Quat(0,0,0,1);
}
else if ( dot < -0.999999 )
{
Vector3 axis = Vector3::cross(Vector3(1,0,0),v2);
if (axis.length() == 0) // pick another if colinear
axis = Vector3::cross(Vector3(0,1,0),v2);
axis.normalize();
q = Quat::axisToQuat(axis,180);
}
else
{
float s = sqrt( (1+dot)*2 );
float invs = 1 / s;
Vector3 c = Vector3::cross(v1, v2);
q.x = c.x * invs;
q.y = c.y * invs;
q.z = c.z * invs;
q.w = s * 0.5f;
}
q.normalize();
return q;
}
What should I change/add to this code, to find the correct rotation?
Before we begin, I will assume that both UP vector and normal vector are normalized and orthogonal (dot product is zero) between them.
Let's say that you want to rotate your yellow plate to be aligned with the rose (red?) plate. So, our reference will be the vectors from yellow plate and we will call our coordinate system as XYZ, where Z -> normal yellow vector, Y -> Up yellow vector and X -> YxZ (cross product).
In the same way, for rose plate, the rotated coordinate system will be called X'Y'Z' where Z' -> normal rose vector, Y' -> up rose vector and X' -> Y'xZ' (cross product).
Ok to find the rotation matrix, we only need to make sure that our normal yellow vector will become normal rose vector; that our up yellow vector will be transfomed in the up rose vector, and so on, i.e.:
RyellowTOrose = |X'x Y'x Z'x|
|X'y Y'y Z'y|
|X'z Y'z Z'z|
in other words, after you have any primitives transformed to be in coordinates of yellow system, applying this transformation, will rotate it to be aligned with rose coordinates system
If your up and normal vector aren't orthogonal, you can correct one of them easily. Just make the cross product between normal and up (results in a vector called C, for convenience) and do again the cross product between with C and normal, to correct the up vector.
First of all, I make the claim that there is only one such transformation that will align the orientation of the two objects. So we needn't worry about finding the shortest one.
Let the object that will be rotated be called a, and call the object that stay stationary b. Let x and y be the normal and up vectors respectively for a, and similarly let u and v be these vectors for b. I will assume x, y, u, and v are unit length, and that is x is orthogonal to y, and u is orthogonal to v. If any of this is not the case code can be written to correct this (via planar projection and normalization).
Now let’s construct matrices defining the “world space” the orientation of a and b. (let ^ denote the cross product) construct z as x ^ y, and construct c as a ^ b. Writing x, y, z and a, b, c to columns of each matrix gives us the two matrices, call them A and B respectively. (the cross product here gives us a unit length and mutually orthogonal vector since the same is true of the operands)
The change of coordinate system transformation to obtain B in terms of A is A^-1 (the inverse of matrix A, where ^ denotes a generalization of an exponent), in this case A^-1 can be computed as A^T, the transpose, since A is an orthogonal matrix by construction. Then the physical transformation to B is just matrix B itself. So, transforming an object by A^-1, and then by B will give the desired result. However these transformations can be concatenated into one transformation by multiplying B on the right into A^-1 on the left.
You end up with this matrix (assuming no arithmetic errors):
_ _
| x0*u0+x1*u1+x2*u2 x0*v0+x1*v1+x2*v2 x0*(u1*v2-u2*v1)+x1*(u2*v0-u0*v2)+x2*(u0*v1-u1*v0) |
| |
| y0*u0+y1*u1+y2*u2 y0*v0+y1*v1+y2*v2 y0*(u1*v2-u2*v1)+y1*(u2*v0-u0*v2)+y2*(u0*v1-u1*v0) |
| |
| (x0*y2-x2*y1)*u0+(x2*y0-x0*y2)*u1+(x0*y1-x1*y0)*u2 (x0*y2-x2*y1)*v0+(x2*y0-x0*y2)*v1+(x0*y1-x1*y0)*v2 (x0*y2-x2*y1)*(u1*v2-u2*v1)+(x2*y0-x0*y2)*(u2*v0-u0*v2)+(x0*y1-x1*y0)*(u0*v1-u1*v0) |
|_ _|
The quaternion code rotates just one vector to another without "Up" vector.
In your case simply build rotation matrix from 3 orthogonal vectors
normalized (unit) direction vector
normalized (unit) up vector
cross product of direction and up vectors.
Than you will have R1 and R2 matrix (3x3) representing rotation of object in two cases.
To find rotation from R1 to R2 just do
R1_to_R2 = R2 * R1.inversed()
And matrix R1_to_R2 is the transformation matrix from one orientation to other. NOTE: R1.inversed() here can be replaced with R1.transposed()

Rotation in OpenGL ES 2.0

I have a 2x4 matrix. which represent 4 points of a square. I need to rotate said square by x radians (which obviously can be converted to degrees) with the rotation point/ anchor being the center of the square.
Since OpenGL ES 2.0 has removed the transformation functions (glPush/glPop, glRotate, glTranslate, glScale, etc.) I need to do the rotation myself. Can someone help me write a function to preform the rotation?
Rotations in 2D can be expressed as (where theta is in radians):
cs = cos(theta);
sn = sin(theta);
out.x = in.x * cs - in.y * sn;
out.y = in.x * sn + in.y * cs;
The above linear equations can be expressed as a 2x2 matrix (in american way, arranged in columns):
| cs sn |
| -sn cs |
The matrix can be expanded to add also translations:
| cs sn tx |
| -sn cs ty |
| 0 0 1 |
In OpengGLES 2.0 you will probably be packing those 4 points as an array of two components, you will need to transform them in a vertex shader. You compute the above matrix and send it down the pipeline using an uniform.
This can get quite long if you don't know OpenGL ES 2.0 pipeline. Do you require more info?

How to convert Euler angles to directional vector?

I have pitch, roll, and yaw angles. How would I convert these to a directional vector?
It'd be especially cool if you can show me a quaternion and/or matrix representation of this!
Unfortunately there are different conventions on how to define these things (and roll, pitch, yaw are not quite the same as Euler angles), so you'll have to be careful.
If we define pitch=0 as horizontal (z=0) and yaw as counter-clockwise from the x axis, then the direction vector will be
x = cos(yaw)*cos(pitch)
y = sin(yaw)*cos(pitch)
z = sin(pitch)
Note that I haven't used roll; this is direction unit vector, it doesn't specify attitude. It's easy enough to write a rotation matrix that will carry things into the frame of the flying object (if you want to know, say, where the left wing-tip is pointing), but it's really a good idea to specify the conventions first. Can you tell us more about the problem?
EDIT:
(I've been meaning to get back to this question for two and a half years.)
For the full rotation matrix, if we use the convention above and we want the vector to yaw first, then pitch, then roll, in order to get the final coordinates in the world coordinate frame we must apply the rotation matrices in the reverse order.
First roll:
| 1 0 0 |
| 0 cos(roll) -sin(roll) |
| 0 sin(roll) cos(roll) |
then pitch:
| cos(pitch) 0 -sin(pitch) |
| 0 1 0 |
| sin(pitch) 0 cos(pitch) |
then yaw:
| cos(yaw) -sin(yaw) 0 |
| sin(yaw) cos(yaw) 0 |
| 0 0 1 |
Combine them, and the total rotation matrix is:
| cos(yaw)cos(pitch) -cos(yaw)sin(pitch)sin(roll)-sin(yaw)cos(roll) -cos(yaw)sin(pitch)cos(roll)+sin(yaw)sin(roll)|
| sin(yaw)cos(pitch) -sin(yaw)sin(pitch)sin(roll)+cos(yaw)cos(roll) -sin(yaw)sin(pitch)cos(roll)-cos(yaw)sin(roll)|
| sin(pitch) cos(pitch)sin(roll) cos(pitch)sin(roll)|
So for a unit vector that starts at the x axis, the final coordinates will be:
x = cos(yaw)cos(pitch)
y = sin(yaw)cos(pitch)
z = sin(pitch)
And for the unit vector that starts at the y axis (the left wing-tip), the final coordinates will be:
x = -cos(yaw)sin(pitch)sin(roll)-sin(yaw)cos(roll)
y = -sin(yaw)sin(pitch)sin(roll)+cos(yaw)cos(roll)
z = cos(pitch)sin(roll)
There are six different ways to convert three Euler Angles into a Matrix depending on the Order that they are applied:
typedef float Matrix[3][3];
struct EulerAngle { float X,Y,Z; };
// Euler Order enum.
enum EEulerOrder
{
ORDER_XYZ,
ORDER_YZX,
ORDER_ZXY,
ORDER_ZYX,
ORDER_YXZ,
ORDER_XZY
};
Matrix EulerAnglesToMatrix(const EulerAngle &inEulerAngle,EEulerOrder EulerOrder)
{
// Convert Euler Angles passed in a vector of Radians
// into a rotation matrix. The individual Euler Angles are
// processed in the order requested.
Matrix Mx;
const FLOAT Sx = sinf(inEulerAngle.X);
const FLOAT Sy = sinf(inEulerAngle.Y);
const FLOAT Sz = sinf(inEulerAngle.Z);
const FLOAT Cx = cosf(inEulerAngle.X);
const FLOAT Cy = cosf(inEulerAngle.Y);
const FLOAT Cz = cosf(inEulerAngle.Z);
switch(EulerOrder)
{
case ORDER_XYZ:
Mx.M[0][0]=Cy*Cz;
Mx.M[0][1]=-Cy*Sz;
Mx.M[0][2]=Sy;
Mx.M[1][0]=Cz*Sx*Sy+Cx*Sz;
Mx.M[1][1]=Cx*Cz-Sx*Sy*Sz;
Mx.M[1][2]=-Cy*Sx;
Mx.M[2][0]=-Cx*Cz*Sy+Sx*Sz;
Mx.M[2][1]=Cz*Sx+Cx*Sy*Sz;
Mx.M[2][2]=Cx*Cy;
break;
case ORDER_YZX:
Mx.M[0][0]=Cy*Cz;
Mx.M[0][1]=Sx*Sy-Cx*Cy*Sz;
Mx.M[0][2]=Cx*Sy+Cy*Sx*Sz;
Mx.M[1][0]=Sz;
Mx.M[1][1]=Cx*Cz;
Mx.M[1][2]=-Cz*Sx;
Mx.M[2][0]=-Cz*Sy;
Mx.M[2][1]=Cy*Sx+Cx*Sy*Sz;
Mx.M[2][2]=Cx*Cy-Sx*Sy*Sz;
break;
case ORDER_ZXY:
Mx.M[0][0]=Cy*Cz-Sx*Sy*Sz;
Mx.M[0][1]=-Cx*Sz;
Mx.M[0][2]=Cz*Sy+Cy*Sx*Sz;
Mx.M[1][0]=Cz*Sx*Sy+Cy*Sz;
Mx.M[1][1]=Cx*Cz;
Mx.M[1][2]=-Cy*Cz*Sx+Sy*Sz;
Mx.M[2][0]=-Cx*Sy;
Mx.M[2][1]=Sx;
Mx.M[2][2]=Cx*Cy;
break;
case ORDER_ZYX:
Mx.M[0][0]=Cy*Cz;
Mx.M[0][1]=Cz*Sx*Sy-Cx*Sz;
Mx.M[0][2]=Cx*Cz*Sy+Sx*Sz;
Mx.M[1][0]=Cy*Sz;
Mx.M[1][1]=Cx*Cz+Sx*Sy*Sz;
Mx.M[1][2]=-Cz*Sx+Cx*Sy*Sz;
Mx.M[2][0]=-Sy;
Mx.M[2][1]=Cy*Sx;
Mx.M[2][2]=Cx*Cy;
break;
case ORDER_YXZ:
Mx.M[0][0]=Cy*Cz+Sx*Sy*Sz;
Mx.M[0][1]=Cz*Sx*Sy-Cy*Sz;
Mx.M[0][2]=Cx*Sy;
Mx.M[1][0]=Cx*Sz;
Mx.M[1][1]=Cx*Cz;
Mx.M[1][2]=-Sx;
Mx.M[2][0]=-Cz*Sy+Cy*Sx*Sz;
Mx.M[2][1]=Cy*Cz*Sx+Sy*Sz;
Mx.M[2][2]=Cx*Cy;
break;
case ORDER_XZY:
Mx.M[0][0]=Cy*Cz;
Mx.M[0][1]=-Sz;
Mx.M[0][2]=Cz*Sy;
Mx.M[1][0]=Sx*Sy+Cx*Cy*Sz;
Mx.M[1][1]=Cx*Cz;
Mx.M[1][2]=-Cy*Sx+Cx*Sy*Sz;
Mx.M[2][0]=-Cx*Sy+Cy*Sx*Sz;
Mx.M[2][1]=Cz*Sx;
Mx.M[2][2]=Cx*Cy+Sx*Sy*Sz;
break;
}
return(Mx);
}
FWIW, some CPU's can compute Sin & Cos simultaneously (for example fsincos on x86). If you do this, you can make it a bit faster with three calls rather than 6 to compute the initial sin & cos values.
Update: There are actually 12 ways depending if you want right-handed or left-handed results -- you can change the "handedness" by negating the angles.
Beta saved my day. However I'm using a slightly different reference coordinate system and my definition of pitch is up\down (nodding your head in agreement) where a positive pitch results in a negative y-component. My reference vector is OpenGl style (down the -z axis) so with yaw=0, pitch=0 the resulting unit vector should equal (0, 0, -1).
If anyone comes across this post and has difficulties translating Beta's formulas to this particular system, the equations I use are:
vDir->X = sin(yaw);
vDir->Y = -(sin(pitch)*cos(yaw));
vDir->Z = -(cos(pitch)*cos(yaw));
Note the sign change and the yaw <-> pitch swap. Hope this will save someone some time.
You need to be clear about your definitions here - in particular, what is the vector you want? If it's the direction an aircraft is pointing, the roll doesn't even affect it, and you're just using spherical coordinates (probably with axes/angles permuted).
If on the other hand you want to take a given vector and transform it by these angles, you're looking for a rotation matrix. The wiki article on rotation matrices contains a formula for a yaw-pitch-roll rotation, based on the xyz rotation matrices. I'm not going to attempt to enter it here, given the greek letters and matrices involved.
If someone stumbles upon looking for implementation in FreeCAD.
import FreeCAD, FreeCADGui
from FreeCAD import Vector
from math import sin, cos, pi
cr = FreeCADGui.ActiveDocument.ActiveView.getCameraOrientation().toEuler()
crx = cr[2] # Roll
cry = cr[1] # Pitch
crz = cr[0] # Yaw
crx = crx * pi / 180.0
cry = cry * pi / 180.0
crz = crz * pi / 180.0
x = sin(crz)
y = -(sin(crx) * cos(crz))
z = cos(crx) * cos(cry)
view = Vector(x, y, z)