I have a two 3D vectors A, B and the angle alpha between these two vectors. I would like to change this angle and rotate vector B by 3/7 of angle alpha towards vector A.
How can I do this in the simplest way?
My current approach is to create a matrix describing a plane based on on both vectors, then multiplying rotation matrix with angle 3/7 of alpha, where alpha is determined from cross product of A and B.
Well, it works, but I think it is an overkill and could be simplified. Any ideas?
You could create the cross-product. This vector then is the basis for a quaternion rotation that goes 3/7alpha.
Under the hood though all of this will always boil down to the same maths. So if your solution works, encapsulate it into a function & be happy. And the matrix is advantageous (regardless of where you got it from, quaternion or by your means) because it can be composed with others, e.g. local to world coordinates.
Related
I've got the following problem:
In 3D there's a vector from fixed the center of a plane to the origin. This plane has arbitrary coordinates around this center thus its normal vector is not necessarily the mentioned vector. Therefore I have to rotate the plane around this fixed center such that the mentioned vector is the plane's normal vector.
My first idea was to compute the angle between the vector and the normal vector, but the problem then is how to rotate the plane.
Any ideas?
A plane is a mathematical entity which satisfies the following equation:
Where n is the normal, and a is any point on the plane (in this case the center point as above). It makes no sense to "rotate" this equation - if you want the plane to face a certain direction, just make the normal equal to that direction (i.e. the "mentioned" vector).
You later mentioned in the comments that the "plane" is an OpenGL quad, in which case you can use Quaternions to compute the rotation.
This Stackoverflow post tells you how to compute the rotation quaternion from your current normal vector to the "mentioned" vector. This site tells you how to convert a quaternion into a rotation matrix (whose dimensions are 3x3).
Let's suppose the center point is called q, and that the rotation matrix you obtain has the following form:
This can only rotate geometry about the origin. A rotation about a general point requires a 4x4 matrix (what OpenGL uses), which can be constructed as follows:
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.
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 :)
I have a Plane class that holds n for normal and q for a point on the plane. I also have another point p that also lies on that plane. How do I go about rounding p to the nearest unit on that plane. Like snapping a cursor to a 3D grid but the grid can be rotating plane.
Image to explain:
Red is the current point. Green is the rounded point that I'm trying to get.
Probably the easiest way to achieve this is by taking the plane to define a rotated and shifted coordinate system. This allows you to construct the matrices for transforming a point in global coordinates into plane coordinates and back. Once you have this, you can simply transform the point into plane coordinates, perform the rounding/projection in a trivial manner, and convert back to world coordinates.
Of course, the problem is underspecified the way you pose the question: the transformation you need has six degrees of freedom, your plane equation only yields three constraints. So you need to add some more information: the location of the origin within the plane, and the rotation of your grid around the plane normal.
Personally, I would start by deriving a plane description in parametric form:
xVec = alpha*direction1 + beta*direction2 + x0
Of course, such a description contains nine variables (three vectors), but you can normalize the two direction vectors, and you can constrain the two direction vectors to be orthogonal, which reduces the amount of freedoms back to six.
The two normalized direction vectors, together with the normalized normal, are the base vectors of the rotated coordinate system, so you can simply construct the rotation matrix by putting these three vectors together. To get the inverse rotation, simply transpose the resulting matrix. Add the translation / inverse translation on the appropriate side of the rotation, and you are done.
I'm trying to rotate a point on a plane around the normal of the plane with a certain angle (so it stays on the plane).
For example:
Point = (0,0,1) (on the plane)
Normal = (0,1,0)
Angle = 33 degrees
But can't seem to figure out how to do it
EDIT:
The axis of rotation always passes through the origin (0,0,0)
If you're looking for axis-angle rotations in 3-space, Rodrigues's Rotation Formula is very useful. The Wikipedia page is pretty good: here
Probably not optimal, but: find the span vectors of the plane (call them U and V), express the point P in terms of U and V and apply 2D rotation. PS: a normal does not fully define a plane; you need at least a point in the plane in addition.
To compute the rotation matrix you want, you will need a bit of linear algebra. There is an article on Wikipedia which explains what you need to do.