How do I invert two axes of a quaternion - opengl

I have to convert poses (coordiantes + quaternion for rotation) from two different APIs I'm using. More specifically I get coordinates of objects relative to the camera's local position.
My detection library (for detecting those objects) has the coordinate system of the camera oriented with Z in the direction the camera is looking, X to the right of the camera, and Y down from the camera (if you look from the perspective of the camera itself). I will use ACII Art here to show what I mean:
Symbols:
+------+
| | = camera from the back
+------+
+--+
| +-+
| | = camera from the right side (imagine the front part as the lens)
| +-+
+--+
Detection Coordinate System from the back of the camera
+--------> x
|
| +------+
| | |
V y +------+
Detection Coordinate System from the right side of the camera
+--------> z
| +--+
| | +-+
| | |
V y | +-+
+--+
The library where I use the object poses however has X in the same direction, but Y and Z are both inverted. So Z is pointing opposite the looking direction of the camera and Y is pointing straight up. More ASCII sketches:
Usage Coordinate System from the back of the camera
^ y +------+
| | |
| +------+
|
+--------> x
Usage Coordinate System from the right side of the camera
+--+
| +-+ ^ y
| | |
| +-+ |
+--+ |
z <--------+
So now I get object poses (including rotation) in the detection coordinate system but want to use them in the usage coordinate system. I know I can transform the coordinates by just inverting the values for y and z, but how do I convert the quaternions for the rotation? I tried a few combinations but none seem to work.

In this case your change of basis are just permutations of the axes, so to convert from one to the other you just have to replicate the same permutation in the imaginary vector in the quaternion.
i.e. if your quaternion is (w,x,y,z) and the basis permutation is (z,y,x) your new quaternion is (w,z,y,x).

Related

Generating spheres with vertices and indices?

I'm currently working on an OpenGL project where I should currently generate spheres with vertices and indices.
All vertices represent a point, and indices tells the graphic card to link 3 points as a triangle.
Example : indices : {0,1,2} = it will make a triangle with the first, second and third point.
I've managed to make a UV sphere with correct vertices, but I don't know how I can get indices.
Here is my current result :
And here is my code :
Mesh ObjectFactory::createSphere() {
// Texture loaded and binded to the shaderprogram
Texture textures[]{
Texture("resources/pop_cat.png", "diffuse", 0, GL_RGBA, GL_UNSIGNED_BYTE),
};
int numHorizontalSegments = 20;
int numVerticalSegments = 20;
Vertex vertices[numVerticalSegments * numVerticalSegments] = {};
GLuint indices[numVerticalSegments * numVerticalSegments] = {};
int i = 0;
for (int h = 0; h < numHorizontalSegments; h++) {
float angle1 = (h + 1) * M_PI / (numHorizontalSegments + 1);
for (int v = 0; v < numVerticalSegments; v++) {
i++;
float angle2 = v * (2 * M_PI) / numVerticalSegments;
float x = sinf(angle1) * cosf(angle2);
float y = cosf(angle1);
float z = sinf(angle1) * sinf(angle2);
vertices[i] = Vertex{glm::vec3(x, y, z), glm::vec3(0.83f, 0.70f, 0.44f), glm::vec2(0.0f, 0.0f)};
indices[i] = i;
}
}
// Store mesh data in vectors for the mesh
std::vector<Vertex> verts(vertices, vertices + sizeof(vertices) / sizeof(Vertex));
std::vector<GLuint> ind(indices, indices + sizeof(indices) / sizeof(GLuint));
std::vector<Texture> tex(textures, textures + sizeof(textures) / sizeof(Texture));
// Create sphere mesh
return {verts, ind, tex};
}
Thank you a lot for your help !
You have created a sphere of vertices by calculating horizontal circles in multiple vertical layers, a UV sphere. Good.
You are just adding indexes once for each vertex for a total of one index per vertex, that is not according to the concept.
What you need to repeatedy do is finding the three indexes in your array of vertices, which make a usable triangle.
Among other things it means that you will name the same vertex index multiple times. Mostly six times, because most of your vertices will be part of six triangles. At least one to the "upper left", one towards the "upper right", "lower left", "lower right"; while there are usually two double directions; e.g. two triangles to the upper right.
"mostly six", because of edge cases like the "north pole" and "south pole"; which participate in many triangles and quads.
Lets looks at a part of your UV sphere:
V03----------V02----------V01---------V00
| | __/ | __/|
| | __/ | c __/ |
| | __/ | __/ |
| | / f | / d |
V13----------V12----------V11----------V10
| | __/ | e __/|
| | a __/ | __/ |
| | __/ | __/ |
| | / b | / |
V23----------V22----------V21----------V20
| | | |
| | | |
| | | |
| | | |
V33----------V32----------V31---------V30
You can see that for the quad in the middle (represented by two triangles "a" and "b"),
you need six index entries, though it only has 4 of the vertices, and each of the vertices will be used even more often, from the other touching quads.
For the triangle "a" you get indexes for the vertexes V11, V12, V22 (mind the orientation, depending on where you want the surface, thinking either always "counter clock" or always "clockwise" will get you where you only need a few tries to get the desired result).
For the triangle "b" you get indexes for the vertexes V11, V22, V21.
Also, the vertex V11 will have to be index again for the triangle "c" and "d", and "e", and "f"; for participating in six triangles or four quads.
You managed to do your UV sphere fine, so I do not think that I need to provide the loop and selection code for getting that done. You managed to visualise the result of your UV sphere, just try and retry after checking the result.

C++ Rotating Cube in Coordinates (non-draw)

I've been looking for this for quite a long time without any results, been trying to figure out the math for this myself for about a week+.
My goal is to set my cursor position(s) so in the way that it forms a rotating cube much in the way like an OpenGL rotating cube border box would.
Since OpenGL has a rotate function built it, it's not really something I can adapt to.
I just wonder if anyone has any ideas how I'd go about this.
If you're wondering what the point of this is, on each created frame(cube rotating point) it has a function to erase anything drawn in MsPaint and then the next positions begin drawing, basically to create a spinning cube being drawn.
If you try to rotate cube in C without help of any specialized library you should use Matrix operations to transform coordinates.
You sohuld get roatation matrix (Let's call it M)
You should multiply M to your coordinates vector - result is new
coordinates.
for 2D rotation, example (f - rotation angle, +- is rotation direction):
|cos f +-sin f| |x| |x'|
| | | | = | |
|+-sin f cos f| |y| |y'|
for 3D rotation, you should use 3x3 marix. Alsoo you should rotation axis, depending on it you should choose matrix M:
Mx (rotate around x axis):
|1 0 0 ||x| |x'|
|0 cos f -sin f||y| = |y'|
|0 sin f cos f||z| |z'|
My (rotate around y axis):
|cos f 0 sin f ||x| |x'|
| 0 1 0 ||y| = |y'|
|-sin f 0 cos f ||z| |z'|
Mz (rotate around z axis):
| cos f -sin f 0 ||x| |x'|
| sin f cos f 0 ||y| = |y'|
| 0 0 1 ||z| |z'|

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 interpret the VtkCamera viewTransformMatrix

I have an object at the origin and am moving the camera to (0,650,650) and setting the focal point to the origin i.e.:
vtkSmartPointer<vtkCamera> cam = vtkSmartPointer<vtkCamera>::New();
renderer->SetActiveCamera(cam);
cam->SetFocalPoint(0., 0., 0.);
cam->SetPosition(0., 650, 650);
cam->SetViewAngle(view_angle_);
cam->SetViewUp(0., 1., 0.);
However when I get the view transform matrix of the camera by:
vtkSmartPointer<vtkMatrix4x4> transform_view = cam->GetViewTransformMatrix();
And print it I get the following:
| 1 | 0 | 0 | 0 |
| 0 | cos(45) | -sin(45)| 0 |
| 0 | sin(45) | cos(45) | -919.239 |
| 0 | 0 | 0 | 1 |
Where the rotation part seems correct (45 degrees around the x axis) but the translation seems all wrong. Should the last column not be:
| 0 |
|650|
|650|
Or am I doing something wrong?
It's an old question, but I'll give an answer for the record.
What you expect is the transform w_T_c, i.e. from the camera frame to the world frame.
What GetViewTransformMatrix method returns, is c_T_w, i.e. the transform from the world to the camera frame: given a point in the world frame p_w, its coordinates in the camera frame are p_c = c_T_w * p_w.
In your example, if you inverted your matrix, in the last column you would get the translation values you were looking for.
The focal point is not the same as the "look at" point. The focal point may be in front of or behind the camera. It's the point through which all of the rays of your scene will pass to give your view perspective. Those rays are projected onto the view plane, which is what is rendered.
If you want to look at the origin, you need to set your View Plane Normal vector to be a normalized vector pointing from your camera location to the origin. So, if your camera location is at location L, the View Plane Normal vector should be -L/||L|| where || || is the l-2 norm.

Convention of faces in OpenGL cubemapping

What is the convention OpenGL follows for cubemaps?
I followed this convention (found on a website) and used the correspondent GLenum to specify the 6 faces GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT but I always get wrong Y, so I have to invert Positive Y with Negative Y face. Why?
________
| |
| pos y |
| |
_______|________|_________________
| | | | |
| neg x | pos z | pos x | neg z |
| | | | |
|_______|________|________|________|
| |
| |
| neg y |
|________|
but I always get wrong Y, so I have to invert Positive Y with Negative Y face. Why?
Ah, yes, this is one of the most odd things about Cube Maps. Rest assured, you're not the only one to fall for it. You see:
Cube Maps have been specified to follow the RenderMan specification (for whatever reason), and RenderMan assumes the images' origin being in the upper left, contrary to the usual OpenGL behaviour of having the image origin in the lower left. That's why things get swapped in the Y direction. It totally breaks with the usual OpenGL semantics and doesn't make sense at all. But now we're stuck with it.
Take note that upper left, vs. lower left are defined in the context of identity transformation from model space to NDC space
Here is a convenient diagram showing how the axes work in OpenGL cubemaps: