View Matrix from Quaternion - c++

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.

Related

Convert 3 axis vectors to axis/angle

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.

What exactly happens after run Algorithm PCA (Principal Component Analysis)

At this moment I'm working with an image processing project. But I have a conceptual questions regarding the PCA.
What exactly happens to the matrix after applying the PCA in the matrix of an image?
I does not understand reading the literature on this subject.
Given an M x N matrix, the result is an matrix M' x N' and where M'< M and N' < N and M' x N' is proporcional to M x N?
I'm no expert in PCA but I'll try to explain what I understand.
After apply PCA to the matrix of an image, you get the eigenvectors of that matrix, which represents a number invariant axis of the matrix. These vectors are all orthogonal to each other.
By measuring how disperse are your original data in matrix along these vectors, you can know how are they distributed. This can be useful, for example, if you wish to perform pattern categorization based on how the data are distributed along these "axis".
Although not accurate, you can imagine PCA helps you to draw "axis" along the blob of data that presence in your matrix, where the new "origin" of the axis are the center of your data.
The best part is that the data are distributed the most along the first eigenvector, follow by the second eigenvector and so on.
I hope I did not confused you.
There are a number of good reference about PCA in quora in addition to stackoverflow too.
Here are a few examples:
https://www.quora.com/What-is-an-intuitive-explanation-for-PCA
http://www.quora.com/How-to-explain-PCA-in-laymans-terms
Again, I'm no expert and welcome others to correct/educate both rwvaldivia and me.
The concept of PCA is closely related to linear algebra, which is the domain of mathematics to which matrices belong. A common way to view a matrix is as a set of vectors, a MxN matrix are just M vectors in an N-dimensional space.
Now a general concept in linear algebra is that the choice of basis vectors is pretty arbitrary. If you choose another basis, you convert your matrix by multiplying it with the old basis expressed in the new basis (an NxN dimensional matrix itself).
PCA is a method to find a basis which isn't arbitrary, but specific to your matrix. In particular, it orders base vectors by the amount in which they're present in your set of vectors. If all your vectors point roughly in the same direction, that direction will be the first basis vector. If they're all roughly in the same plane, the major basis vectors for that plane will be your first two vectors. But remember: you'll generally a full MxN basis (unless your matrix is degenerate); it's up to you to decide how many of the Components are Principal.
Now here's the real question: what exactly is "the matrix of the image"? You generally can't treat a 1024 x 768 image as a set of 1024 vectors in 768-dimensional space. Sure, you can perform the PCA operation, and you will get a 1024x768 result matrix, but what does that even mean? They're the basis vectors of your input matrix, but that output doesn't have an image meaning exactly because your input is not a set of vectors.

What does it mean to normalize a value?

I'm currently studying lighting in OpenGL, which utilizes a function in GLSL called normalize. According to OpenGL docs, it says that it "calculates the normalized product of two vectors". However, it still doesn't explain what "normalized" mean. I have tried look for what a normalized product is on Google, however I can't seem to find anything about it. Can anyone explain what normalizing means and provide a few example of a normalized value?
I think the confusion comes from the idea of normalizing "a value" as opposed to "a vector"; if you just think of a single number as a value, normalization doesn't make any sense. Normalization is only useful when applied to a vector.
A vector is a sequence of numbers; in 3D graphics it is usually a coordinate expressed as v = <x,y,z>.
Every vector has a magnitude or length, which can be found using Pythagora's theorem: |v| = sqrt(x^2 + y^2 + z^2) This is basically the length of a line from the origin <0,0,0> to the point expressed by the vector.
A vector is normal if its length is 1. That's it!
To normalize a vector means to change it so that it points in the same direction (think of that line from the origin) but its length is one.
The main reason we use normal vectors is to represent a direction; for example, if you are modeling a light source that is an infinite distance away, you can't give precise coordinates for it. But you can indicate where to find it from a particular point by using a normal vector.
It's a mathematical term and this link explains its meaning in quite simple terms:
Operations in 2D and 3D computer graphics are often performed using copies of vectors that have been normalized ie. converted to unit vectors... Normalizing a vector involves two steps:
calculate its length, then,
divide each of its (xy or xyz) components by its length...
It's something complicated to explain if you don't know too much about vectors or even vectorial algebra. (You can check this article about general concepts as vector, normal vector or even normalization procedure ) Check it
But the procedure or concept of "normalize" refers to the process of making something standard or “normal.”
In the case of vectors, let’s assume for the moment that a standard vector has a length of 1. To normalize a vector, therefore, is to take a vector of any length and, keeping it pointing in the same direction, change its length to 1, turning it into what is called a unit vector.

Transformation Matrix Multiplication by matrix type, C++

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

Fitting data to a 3rd degree polynomial

I'm currently writing a C++ program where I have vectors of independent and dependent data that I would like to fit to a cubic function. However, I'm having trouble generating a polynomial that can fit my data.
Part of the problem is that I can't use various numerical packages, such as GSL (long story); it's possible that it might even be overkill for my case. I don't need a very generalized solution for least squares fitting. I specifically want to fit my data to a cubic function. I do have access to Sony's vector library, which supports 4x4 matrices and can calculate their inverses, among other things.
While prototyping this in Scilab, I used a function like:
function p = polyfit(x, y, n)
m = length(x);
aa = zeros(m, n+1)
aa(:,1) = ones(m,1)
for k = 2:n+1
aa(:,k) = x.^(k-1)
end
p = aa\y
endfunction
Unfortunately, this doesn't map well to my current environment. The above example needs to support a matrix of M x N+1 dimensions. In my case, that's M x 4, where M depends on how much sample data that I have. There's also the problem of left division. I would need a matrix library that supported the inverse of matrices of arbitrary dimensions.
Is there an algorithm for least squares where I can avoid having to calculate aa\y, or at least limit it to a 4x4 matrix? I suppose that I'm trying to rewrite the above algorithm into a simpler case that works for fitting to a cubic polynomial. I'm not looking for a code solution, but if someone can point me in the right direction, I'd appreciate it.
Here is the page I am working from, although that page itself doesn't address your question directly. The summary of my answer would be:
If you can't work with Nx4 matrices directly, then do those matrix
computations "manually" until you have the problem down to something that has only 4x4 or smaller matrices. In this answer I'll outline how to do the specific matrix computations you need "manually."
--
Let's suppose you have a bunch of data points (x1,y1)...(xn,yn) and you are looking for the cubic equation y = ax^3 + bx^2 + cx + d that fits those points best.
Then following the link above, you'd write this equation:
I'll write A, x, and B for those matrices. Then following my link above, you'd like to multiply by the transpose of A, which will give you the 4x4 matrix AT*A that you can invert. In equations, the following is the plan:
A * x = B .................... [what we started with]
(AT * A) * x = AT * B ..... [multiply by AT]
x = (AT * A)-1 * AT * B ... [multiply by the inverse of AT * A]
You said you are happy with inverting 4x4 matrices, so if we can code a way to get at these matrices without actually using matrix objects, we should be okay.
So, here is a method, although it might be a little bit too much like making your own matrix library for your taste. :)
Write an explicit equation for each of the 16 entries of the 4x4 matrix. The (i,j)th entry (I'm starting with (0,0)) is given by
x1i * x1j + x2i * x2j + ... + xNi * xNj.
Invert that 4x4 matrix using your matrix library. That is (AT * A)-1.
Now all we need is AT * B, which is a 4x1 matrix. The ith entry of it is given by x1i * y1 + x2i * y2 + ... + xNi * yN.
Multiply our hand-created 4x4 matrix (AT * A)-1 by our hand-created 4x1 matrix AT * B to get the 4x1 matrix of least-squares coefficients for your cubic.
Good luck!
Yes, we can limit the problem to computing with "a 4x4 matrix". The least squares fit of a cubic, even for M data points, only requires the solution of four linear equations in four unknowns. Assuming all the x-coordinates are distinct the coefficient matrix is invertible, so in principle the system can be solved by inverting the coefficient matrix. We assume that M is more than 4, as would typically be the case for least squares fits.
Here's a write-up for Maple, Fitting a cubic to data, that hides almost completely the details of what is being solved. The first-order minimum criteria (first derivatives with respect to coefficients as parameters of sum of squares error) gets us the four linear equations, often called the normal equations.
You can "assemble" these four equations in code, then apply your matrix inverse or a more sophisticated solution strategy. Obviously you need to have the data points stored in some form. One possibility is two linear arrays, one for the x-coordinates and one for the y-coordinates, both of length M the number of data points.
NB: I'm going to discuss this matrix assembly in terms of 1-based array subscripts. The polynomial coefficients are actually one application where 0-based array subscripts make things cleaner and simpler, but rewriting it in C or any other language that favors 0-based subscripts is left as an exercise for the reader.
The linear system of normal equations is most easily expressed in matrix form by referring to an Mx4 array A whose entries are powers of x-coordinate data:
A(i,j) = x-coordinate of ith data point raised to power j-1
Let A' denote the transpose of A, so that A'A is a 4x4 matrix.
If we let d be a column of length M containing the y-coordinates of data points (in the given order), then the system of normal equations is just this:
A'A u = A' d
where u = [p0,p1,p2,p3]' is the column of coefficients for the cubic polynomial with least squares fit:
P(x) = p0 + p1*x + p2*x^2 + p3*x^3
Your objections seem to center on a difficulty in storing and/or manipulating the Mx4 array A or its transpose. Therefore my answer will focus on how to assemble matrix A'A and column A'd without explicitly storing all of A at one time. In other words we will be doing the indicated matrix-matrix and matrix-vector multiplications implicitly to get a 4x4 system that you can solve:
C u = f
If you think about the entry C(i,j) being the product of the ith row of A' with the jth column of A, plus the fact that the ith row of A' is really just the transpose of the ith column of A, it should be clear that:
C(i,j) = SUM x^(i+j-2) over all data points
This is certainly one place where the exposition would be simplified by using 0-based subscripts!
It might make sense to accumulate the entries for matrix C, which depend only on the value of i+j, i.e. a so-called Hankel matrix, in a linear array of length 7 such that:
W(k) = SUM x^k over all data points
where k = 0,..,6. The 4x4 matrix C has a "striped" structure that means only these seven values appear. Looping over the list of x-coordinates of data points, you can accumulate the appropriate contributions of each power of each data point in the appropriate entry of W.
A similar strategy can be used to assemble the column f = A' d, namely to loop over the data points and accumulate the following four summations:
f(k) = SUM (x^k)*y over all data points
where k = 0,1,2,3. [Of course in the above sums the values x,y are the coordinates for a common data point.]
Caveats: This satisfies the goal of working only with a 4x4 matrix. However one typically tries to avoid the explicit formation of the matrix of coefficients for the normal equations because these matrices are often what in numerical analysis is called ill-conditioned. In particular the cases where x-coordinates are closely spaced can cause difficulty when one tries to solve the system by inverting the matrix of coefficients.
A more sophisticated approach to solving these normal equations would be the conjugate gradient method on the normal equations, which can be done with code that computes the matrix-vector products A u and A' v one entry at a time (using what we say above about entries of A).
The accuracy of the conjugate gradient method is often satisfactory because of its natural iterative approach, esp. when one can compute the required dot-products with a little extra precision.
You should never do full matrix inversion for stability reasons. Do LU decomposition and forward-back substitution. The other solutions are spot on otherwise.