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.
Related
https://glm.g-truc.net/0.9.4/api/a00210.html
I'm trying to find the signed angle between two vectors in 3d space.
I can't seem to find what the "reference vector" is in this function, mathematically. Therefore, I don't know how to use the function. Thanks!
There is no such concept as signed angle between two vectors in 3D. If there is no any selected direction, you can get only angle in range 0..Pi (for example, using scalar product, that is invariant to argument order).
Imagine that you drew two vectors A and B (starting from one point) on a glass sheet. Look from one side of glass - you see that you need rotate A by 45 degrees to B. Look from another side - - you see that you need rotate A by -45 degrees to B.
If you have got some reference vector (axis), it helps to define orientation of plane that contains two vectors (positive normal direction), and you can determine also angle sign.
For example, sequence of vectors A, B, Ref may form 'right' oriented triplet (imagine 1st, 2nd, 3rd thumbs on the right hand), so you should turn vector A in positive direction to make it coinciding with vector B, around axis Ref (if Ref is perpendicular both A and B).
Or this sequence may be 'left' triplet, so you should turn vector A in negative direction to make it coinciding with vector B.
(Sorry for my ugly English)
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).
I have a standard scene graph written in opengl with c++.
My scene graph has nodes and shapes.
Nodes are matrices, and they draw all of their children after applying their matrix.
void Node::draw(Affine3f amatrix) const
{
amatrix = amatrix * matrix;
for (Drawable* child : childern)
{
child->draw(amatrix);
}
}
Shapes are simply packaged vbos, they take the matrix from the draw call, set it as the uniform modelview matrix, and then draw the vbo.
void Shape::draw(Affine3f mat) const
{
renderer.setModelView(mat);
myVertices.draw();
}
I love this design, it is very simple and flexible. But, it is very inefficient, with tons of CPU side matrix multiplications and tons of draw calls.
My question is:
How can I optimize this design, removing both unneeded matrix multiplications and unnecessary draw calls?
Like not recalculating matrices each draw(only calculate changed) and uniting the shapes so that they can be drawn with one call.
Some more information:
Shapes are static(for now), the vertices contained will never change.
There is a mix of static geometry(live at root node with no manipulation) and dynamic geometry(children of manipulated nodes)
For one thing, I would pass a const & for the incoming matrices. You are passing by value, and if you have some draw functions that don't end up needing to do anything special with the matrix, it's a lot of unnecessary copying.
If you want to prevent matrix calculations if a matrix hasn't changed, you will need to have a "dirty" flag to determine whether or not a matrix's value changed since you last used it. RenderWare did something like this with its matrix stuff.
Otherwise, like in the comment, without seeing your overall design, there's nothing inherently wrong with what you have.
Are you drawing every element in the tree, even if it isn't visible? If so, you should check out octrees to filter invisible nodes.
You could also try and do most matrix computations in the shaders, by passing them as variables. I also see that your matrices are affine, but maybe you still do an expensive inverse calculation in your implementation. If that's the case, you can check my tutorial to see how to make it cheap.
I'm writing a C++ program to generate a cubic spline trajectory for a set of points. These points need not be sorted along the x-axis. For example, it may be a circle, etc.
I have found some libraries on the web, for example, the ALGLIB library or a class here https://www.marcusbannerman.co.uk/index.php/home/42-articles/96-cubic-spline-class.html, but all of these libraries sort the data points. I do not need this because what I want to generate is something like a circle. Is there anyway to achieve this?
Splines are piecewise functions with respect to some independent variable (usually t, though they seem to use x in the code you have linked). Since the specific function to be evaluated depends on the control points closest to the input value t, it make sense to sort the control points by t so that you can quickly determine the function that needs to be evaluated.
However even if they were not sorted, you still could not create a circle with a single one dimensional spline. Your spline function y = f(t) only gives you one value for any given t. If you are graphing y with respect to t and want a circle with radius 1 about the origin, you would need f(0) to equal both 1 and -1, which doesn't make any sense.
To get something like a circle you instead need a two dimensional spline, or two splines; one for the x value and one for the y value. Once you have these two spline functions f(t) and g(t), then you simply evaluate both functions at the same t and that will give you the x and y values of your spline for that t.
The simple, common trick is to use cumulative linear arclength as the parameter. So, if I have a set of points in a curve as simply (x,y) pairs in the plane where x and y are vectors, do this:
t = cumsum([0;sqrt(diff(x(:)).^2 + diff(y(:)).^2)]);
This gives us the cumulative distance along the piecewise linear segments between each pair of points, presented in the order you have them. Fit the spline curve as two separate spline models, thus x(t) and y(t). So you could use interp1, or use the spline or pchip functions directly. Note that pchip and spline will have different properties when you build that interpolant.
Finally, in the event that you really had a closed curve, so that x(1) and x(end) were supposed to be the same, then you would really want to use a spline model with periodic end conditions. I don't know of any implementations for that except in the spline model in my SLM tools, but it is not difficult to do in theory.