I have this source code which rotate three axis aligned on X, Y and Z:
Quaternion<float> orientation = transform.getOrientation();
Vector3<Vector3<float>> axis(
orientation.rotate(Vector3<float>(1.0, 0.0, 0.0)),
orientation.rotate(Vector3<float>(0.0, 1.0, 0.0)),
orientation.rotate(Vector3<float>(0.0, 0.0, 1.0))
);
From 'axis' variable, I would like to re-build the quaternion. I have a quaternion constructor which allow me to construct it from an axis and an angle.
How can I do that ?
Thank you in advance.
There is a nice Wikipedia page describing Quaternions and spatial rotation. Specifically, the section "Conversion to and from the matrix representation."
Be sure to pay attention to the following point, quoted from that page, "One must be careful when converting a rotation matrix to a quaternion, as several straightforward methods tend to be unstable when the trace (sum of the diagonal elements) of the rotation matrix is zero or very small."
In general, converting from the rotation matrix (which is essentially what you have constructed) to a quaternion is a bad idea. A rotation matrix must be a special orthogonal matrix, which is a very small subset of all possible 3x3 matrices. You will almost always lose some precision when computing the matrix so that it won't be precisely orthogonal. Indeed, this is one of the reasons that quaternions are preferred for representing rotations in 3 dimensions. In general, if you can avoid the conversion and just use quaternions you will be better off.
There is an algorithm on that page that gives a stable method that may be good enough for your purposes. But from personal experience I can tell you that you should expect to lose some precision in the operation in most cases.
Related
When calculating the angle between two vectors, I have traditionally used acos, but this requires the two vectors to be normalised. atan2 can be used to accomplish the same (specifically atan2(b.y_, b.x_) - atan2(a.y_, a.x_)), does this require normalised vectors?
If atan2 doesn't require normalised vectors, would this be better to use since normalisation can be costly and 'more' error prone since it requires a sqrt operation?
Then I read that atan2 itself can be more costly than acos, but more accurate? And then I also read other interwebs suggesting the opposite :( lots of conflicting information, unsure what the deal is with using acos or atan for calculating the angle between two vectors.
Which is recommeneded? and what are the benefits/issues for each usage?
Any help would be appreciated, thanks!
No, atan2 does not require normalized vectors, and if your vectors are not already normalized you shouldn't pre-normalize them as that may slightly reduce precision. The function works correctly for any inputs other than (0,0).
You should never use acos for anything.
I have two objects in 3D space (using OpenGL to render it all) of the same type of a class. These objects store xyz offsets and a rotation matrix representing your standard 4x4 rotational matrix.
A stripped down example:
class object {
float rotMatrix[16];
float xyzTrans[3];
//a displaylist for drawing the object
}
I'm using GLUI for UI controls which makes storing the transformations in format pretty simple.
The problem:
I need to define a "correct" orientation for one object with respect to the other. For example, if the first object is facing directly down the z-axis, and the second one is the same but also rotated roughly 45deg around the x-axis, this would be deemed "correct" and my functions do what they need to do. This can vary of course, maybe its the same z but rotated on the x and y, or maybe even rotated a little bit around each axis. The definition of "correct" rotations will be stored in the object for comparison.
Ideally I'm hoping to do something like:
bool checkRotation(object* first, object* second) {
//do some comparison stuff
if (eachCheck < someTolerance)
return true;
return false;
}
Is this possible to do by comparing two rotational matrices? Do I need to convert to quaternions and use those?
This question is the closest I've found to what I'm asking, but it's just different enough to be confusing.
Not a complete answer, but too long for a comment:
If you have two honest rotation matrices, then they should be invertible, and of determinant 1. Call the matrices A and B. If you want to check that the images A(X) and B(X) of the same object X under the two rotations is "close" in the sense that you can go from A(X) to B(X) by rotation around a specified axis, this is equivalent to checking whether the matrix obtained by taking A times the inverse of B is "nearly" a rotation around that axis. So this is probably the kind of thing you want to look at.
I'm not too familiar with the OpenGL matrix math functions so can't provide any code, sorry.
What is the preferred way of representing a fixed-dimensional plane (struct) in a 3D-graphics when C/C++ is the preferred language.
Should we
store the normalized plane normal vector and origo-distance as separate entities or should we
express them together in a non-normalized vector?
First alternative requires one extra float/double but is other hand more efficient in algorithms that operate on the normal because it is already precalculated. First alternative is also more numerically stable if we vary the normal and offset separately.
Sadly, C++ is not the best language to work with planes. We can at first think that using four floating point values is a good choice as it fits in a SIMD register in SSE and VMX. So we may have a class with a single 128bits member, first three values represent the plane normal and the last a distance ( juste like homogenous coordinate, a plane do not always needs a normalized normal if we only care about the sign of a distance test ).
But when we works with planes to categorize points, sphere, and other volumes, implementing a single plane to point distance function will result to sub-optimal algorithm because most of the time, we know we will test a lot of points against a small number of planes. There is room for optimization !
The problem here has a name, in fact, not the problem, but the way we may represent the information. It's Array Of Structures versus Structure of Arrays ( AOS vs SOA ).
A common exercice in a 3D engine is bounding volume frustum culling ! An usual frustum is made of 6 planes, the right representation is not a Frustum class with a std::array<Plane,6> member, but most likely, 8 SIMD registers layout as : { P0X, P1X, P2X, P3X }, { P4X, P5X, FREEPLANE1X, FREEPLANE2X }, ... and so on for Y, Z and D. Not C++, but much better for SIMD programing.
It may also be useful to prefer a SOA reprensation for points too.
Conclusion : The best representation depends on what algorithm and what kind of data set will go thought your planes.
I'm currently building my own quaternion camera. As far as I know, you only need one quaternion to fully specify the camera's orientation (correct me if I'm wrong). So, how would I go about creating the view matrix? I'm using C++ as a programming language by the way.
Any help would be appreciated.
First some caveats. You'll see lots of apparently conflicting formulae on the 'net and in literature on this subject. Most of the conflicts are apparent only. A few are real conflicts, but that's because somebody got the math wrong. The problem is that there is no single right way to do it. You need to know how you are using quaternions and matrices, how the source is using them, and how to rectify those apparent discrepancies.
Rotation versus transformation
Your camera has a reference frame associated with it, as does the underlying space. Does your matrix represent the physical rotation of the camera from the underlying space to the camera's orientation or the matrix that transforms vectors as represented in the underlying space to the frame of the camera? (Or something else; there are four choices here.) These choices are related; the transformation matrix is the transpose of the rotation matrix. Transformation and rotation are conjugate operations. The same concept applies to quaternions. Are you using transformation quaternions or rotation quaternions? These are once again related concepts; one is the conjugate of the other.
Left versus right quaternions
Given a unit quaternion q to transform or rotate a vector v, some use qvq* to transform/rotate the vector, others use q*vq. Which form is correct? Both are. The two forms differ only in whether the unconjugated quaternion is to the left (qvq*) or to the right (q*vq) of the vector to be transformed/rotated.
Column versus row vectors
Most people use column vectors, but some do use row vectors. Here you run into a left versus right issue with matrices. Column vectors transform/rotate via Mv, with the matrix to the left of the vectors; row vectors via vM, with the matrix on the right.
Impact
You have to be careful in reading the literature. With regard to forming a matrix from a quaternion you need to watch out for sign changes in constructing the off-diagonal elements of the matrix. One formulation's addition/subtraction may change to subtraction/addition in another formulation.
Left transformation quaternions to row vector transformation matrices
I use left transformation quaternions and transformation matrices, and I represent vectors as row vectors. I also represent a quaternion q as comprising a real scalar part qs and a vectorial imaginary part qv. Given these representations, the computations to generate a matrix from a quaternion are (pseudocode):
// Compute the cosine of the rotation angle.
cost = 2.0*qs*qs - 1.0;
// Construct the diagonal of the matrix:
// T_ii = cost + 2qv_i^2
for (i = 0; i < 3; ++i) {
T[i][i] = cost + 2.0*qv[i]*qv[i];
}
// Construct off-diagonal transformation matrix elements:
// T_ij = 2 (qv_i qv_j - eps_ijk qs qv_k), where eps is the Levi-Civita symbol
for (k = 0; k < 3; ++k) {
i = (k+1)%3;
j = (i+1)%3;
T[i][j] = 2.0*(qv[i]*qv[j] - qs*qv[k]);
T[j][i] = 2.0*(qv[i]*qv[j] + qs*qv[k]);
}
You might want to expand those loops out. The first loop expands into three statements, the latter, six. You don't need to compute i and j in the expansion of the latter loop; the expansion of the loop makes them fixed quantities.
Alternate representations
Those caveats above aren't as bad as they seem. You need to make sure my representation is consistent with yours. Odds are 50-50 that it isn't. If it isn't, simply swap the assignments to the off-diagonal elements. Use the computation of T[i][j] for T[j][i], and vice versa. How to tell:
Start with s=1.
Multiply s by -1 if you use rotation quaternions instead of transformation quaternions.
Multiply s by -1 if you use right quaternions instead of left quaternions.
Multiply s by -1 if you use rotation matrices instead of transformation matrices.
Multiply s by -1 if you use row vectors instead of column vectors.
Use my formulation if the final value of s is 1. If it's -1, simply swap the assignments to T[i][j] and T[j][i]. Or you could change the addition to subtraction, the subtraction to addition.
One last gotcha
The above calculation applies when the scalar part is not close to zero. It would be valid everywhere if we had infinite precision arithmetic. You might want to use a separate calculation for rotations that are very close to zero or 180 degrees.
Wikipedia knows it: Quaternions and spatial rotation
I would recommend using the Eigen C++ library to represent your quaternions and matrices. When you have a quaternion object, you can simply call .toRotationMatrix() on it to get a 3x3 matrix.
Another library that would probably work is glm.
The Configurable Math Library ( http://cmldev.net/ ) is a very lightweight lib that could do the computation for you. It is a header library, so integration into your code shouldn't be a problem. This function ( http://cmldev.net/?p=196 ) might help you as well.
Theoretically, let us assume we were to hard-code matrix multiplications for each different combination of 3D Homogeneous (4x4) transformation matrix (translation, rotation, scaling), and then for also each possible result of those (translation-rotation, translation-scaling, scaling-rotation)...
Suppose we were to handle matrix multiplication like that, a different function for each matrix type combination, where each matrix has an extra variable (type), and with the specific functions to use being determined at runtime (using a function pointer array). If we applied this kind of matrix multiplication, could it theoretically be faster than doing basic, standard 4x4 homogeneous matrix multiplication (which is still admittedly faster than generic 4x4 matrix multiplication)?
I'm doing this right now, its kinda hellish to code. I'm going to test it against standard matrix multiplication in the end, and compare results. I just wanted to see what other people think the results might be. Any ideas?
I think a better idea is to store only position and orientation of an object instead of the whole matrix. You only compute the matrix for rendering purpose, once after all transformations. The transformations are done by adding translations (for the position) and multiplying quaternions (for the orientation).