Change the center of rotation with QMatrix4x4
-
I have a "cloud of points" plotted in a 3D space. And I need to do this:
- Move the "cloud of points" to put a selected point in the center of the screen;
- Do all rotations about that selected point.
I am using QMatrix4x4 to modelview and projection matrices. In the shaders I multiply all points by them.
With the modelview matrix I am doing a translation to -P (P is the selected point) and tree rotations (one about each axis). But it does not work....
The translation works well, but the rotations looks to be about the origin....
My code is that:
@ModelView.setToIdentity();
Projection.setToIdentity();
ModelView.lookAt(camera.eye, camera.lookat, camera.up);
ModelView.scale(zoom, zoom, zoom);
ModelView.translate(-prot_selecionada);
ModelView.rotate(rx, QVector3D(1.0, 0.0, 0.0));
ModelView.rotate(ry, QVector3D(0.0, 1.0, 0.0));
ModelView.rotate(rz, QVector3D(0.0, 0.0, 1.0));
Projection.perspective(camera.fovy, 1.0, camera.nearplane, camera.farplane);@What am I doing wrong?
-
Now I haven't done much 3D graphics but here's what I think:
M = T^-1RT
Where T is the translation matrix that moves the desired point of rotation-origin into the mathematical origin. R rotates around the origin. So your code looks like you're missing the inverse T, which is why your mathematical origin still coincides with the rotation-origin. -
[quote author="DerManu" date="1343771328"]Now I haven't done much 3D graphics but here's what I think:
M = T^-1RT
Where T is the translation matrix that moves the desired point of rotation-origin into the mathematical origin. R rotates around the origin. So your code looks like you're missing the inverse T, which is why your mathematical origin still coincides with the rotation-origin.[/quote]I do not think that is the problem, because I am translating the point to mathematical origin and after that I do the rotation.....
If I have a point P = (x, y, z) and I want to rotate about it, what I need to do is:
Translate to -P;
Rotate about the coordinate axes
Translate to P.
In my code the point P is "prot_selecionada", and the code to rotate about it will be:
@ModelView.translate(-prot_selecionada);
ModelView.rotate(rx, QVector3D(1.0, 0.0, 0.0));
ModelView.rotate(ry, QVector3D(0.0, 1.0, 0.0));
ModelView.rotate(rz, QVector3D(0.0, 0.0, 1.0));
ModelView.translate(prot_selecionada);@But what I need is do the rotation around the point "prot_selecionada" and keep it in the mathematical origin, so I do not need to do the second translation.
I think that the problem is not in the theory, the problem looks to be in the QMatrix4x4 rotation....
The documentation says:
"void QMatrix4x4::rotate ( qreal angle, const QVector3D & vector )
Multiples this matrix by another that rotates coordinates through angle degrees about vector."So to the vector I am using the coordinate axis, but it is not working :( .....
I have no idea about what I have to do to fix it.
-
[quote author="DerManu" date="1343851072"]Okay but now I'm not sure what the actual problem is... What do you mean with
"The translation works well, but the rotations looks to be about the origin…." ?[/quote]
Maybe a example will explain better:
I have 50 points plotted in a 3D space, and I pick a point P = (x, y, z). I want to move all 50 points together to make P the center of screen (the mathematical origin (0, 0, 0)). And rotate about the tree coordinate axes. So to do this I use a transformation (4x4) matrix M. I set M to identity, do a translation to (-x, -y, -z) and do tree rotations (one about each axis). Then in the pixel shader I multiply each point by M. So the result which I expect is: the point P goes to the center of the screen and do not matter the angles of rotations the point P stay in the same place, because it is the center of rotation.
But what I have is different... P goes to the center of the screen (this part works), but when I do the rotations they are not about P they are about the point which was the origin C = (0, 0, 0) and now is the (-x, -y, -z), in other words, do not matter the angle of rotations C stay at the same place.
If I am not being clear enough, I can post some pictures.
-
Very strange, very strange. I can't find a systematic or conceptual error here. Are you sure your prot_selecionada has the right data? Have you tried to reduce this to the minimum complexity, i.e. two points with different color at (0,0,0) and (1,0,0) and then applying those matrices? What happens when, in that situation, you translate your origin to (0.5, 0, 0) and then do a rotate?
How are you applying the matrices to the points in the shader? Might the error be there? -
Yes it is very strange.... That is the problem, the theory and the code looks right, but it does not work.....
I made a test with 4 points and recorded a video to really show the problem.
The video is that: http://youtu.be/j2gIQ74GShI
The blue point is the prot_selecionada and I am printing "-prot_selecionada".The code with the transformations is that, and I added a "printf debug" to shows the value of "-prot_selecionada":
@ Matriz_Transformacao.setToIdentity();
Matriz_Projecao.setToIdentity();
Matriz_Transformacao.lookAt(camera.eye, camera.lookat, camera.up);
Matriz_Transformacao.scale(zoom, zoom, zoom);
printf("-prot_selecionada = (%f, %f, %f)\n", -prot_selecionada.x(), -prot_selecionada.y(), -prot_selecionada.z());
fflush(stdout);
Matriz_Transformacao.translate(-prot_selecionada);
Matriz_Transformacao.rotate(rx, QVector3D(1.0, 0.0, 0.0));
Matriz_Transformacao.rotate(ry, QVector3D(0.0, 1.0, 0.0));
Matriz_Transformacao.rotate(rz, QVector3D(0.0, 0.0, 1.0));
Matriz_Projecao.perspective(camera.fovy, 1.0, camera.nearplane, camera.farplane);m_shaderProgram->setUniformValue("MatrixTransformation", Matriz_Transformacao); m_shaderProgram->setUniformValue("MatrixProjection", Matriz_Projecao);@
My shaders are very simple, the pixel shader is that:
@attribute vec4 Pos_Vertice;
attribute vec4 Cor_Vertice;
uniform mat4 MatrixTransformation;
uniform mat4 MatrixProjection;varying vec4 color;
void main()
{
gl_Position = MatrixProjection * MatrixTransformation * Pos_Vertice;
color = Cor_Vertice;
}
@And the fragment shader is that:
@varying vec4 color;void main()
{
gl_FragColor = color;
}
@I have tried every test that I could think... And I have no idea about what I should do to make it works...
-
I've done some tests (The video was very helpful, because you immediately see what's going on):
@ QMatrix4x4 M, R, T;
T.translate(1.0, 0.0, 0.0);
R.rotate(90.0, QVector3D(0.0, 0.0, 1.0));M.translate(1.0, 0.0, 0.0);
M.rotate(90.0, QVector3D(0.0, 0.0, 1.0));
qDebug() << (M == RT) << (M == TR);@
returns "false true".So when you do translate and then rotate to a QMatrix4x4 it results in TR and not RT as you want. Since the points are right-multiplied (as usual in mathematics): TRp the points are rotated first and then translated.
In my opinion that's Qt doing unituitive things. I'd have expected the translate, rotate, etc. functionts to left-multiply their respective transformation matrix and not right-multiply, because when I call a function after another one, I also want its transformation to be applied after the transformation of the other function to a point I apply the final matrix to.Anyway, I think that solves your problem.
-
DerManu, you saved my life!!!! I would never think about it! I have stated to think that rotation in QMatrix4x4 always is done about the origin, ignoring the translations...
Qt is really doing a very unituitive thing... :( And the documentation do not tell us about it....
I will do a bug report, it need to be fixed or be very clear in the documentation!!!Anway, you solved my problem, and I am very happy!!! Very very thanks!!!
-
DerManu, I found a bug report about it: https://bugreports.qt-project.org/browse/QTBUG-20752. If you can add a vote to this bug it will be great, and it will help the "bug" be solved faster.
-
Great to see it works now. (For Science!! ;)
I've upvoted the bug.If you want you can in return upvote "my bug":https://bugreports.qt-project.org/browse/QTBUG-26013 that's annoying me ;).