2

I want to make an object defined in the modeling space to translate in viewing space. The amount of translation is controlled by clicking and dragging the mouse (varying deltaX and deltaY). And here's the code that works well: (reference https://gist.github.com/ptbrowne/2048812)

glPushMatrix();
glLoadMatrixd(cam2wld[cameraIndex].matrix());
glTranslated(deltaX, deltaY, 0);
glMultMatrixd(wld2cam[cameraIndex].matrix());
glMultMatrixd(obj2wld.matrix());
glGetDoublev(GL_MODELVIEW_MATRIX, obj2wld.matrix());
glPopMatrix();

I also want to rotate the object with respect to the camera(screen)'s x-axis, which the amount of rotation is dependent on the mouse dragging again. However, by changing from

glTranslated(deltaX, deltaY, 0);

to

glRotated(deltaX + deltaY, 1, 0, 0);

The object is translated instead. Any idea how to solve the problem? Thanks.

Rabbid76
  • 142,694
  • 23
  • 71
  • 112
Noober
  • 23
  • 4
  • 2
    A rotation happens always about origin. If you want to rotate something about an arbitrary center/axis in space then you have to combine it with resp. translations to move that center to origin before rotation and revert the translation afterwards. Maybe, this may help to understand: [SO: Rotate an image in C++ without using OpenCV functions](https://stackoverflow.com/a/56985104/7478597). (It has nothing to do with OpenGL but transformations are covered a bit, and there is no difference regarding this in 2D and 3D.) – Scheff's Cat Apr 23 '20 at 05:52

1 Answers1

2

I assume that wld2cam[cameraIndex] is the view matrix and cam2wld[cameraIndex] is the inverse view matrix:

glLoadMatrixd(cam2wld[cameraIndex].matrix());
glRotated(deltaY, 1, 0, 0);
glMultMatrixd(wld2cam[cameraIndex].matrix());

What you actually do is to rotate the the model around the point of view. The rotation axis (1, 0, 0) is the view space x-axis. If the distance of the camera to the model is large and the angle is small, this rotation appears to be a translation:

You have to define a pivot for the rotation. For instance the origin of the world. In view space the origin of the world:

const GLdouble *viewMat = cam2wld[cameraIndex].matrix();
GLdouble pivotX = viewMat[12];
GLdouble pivotY = viewMat[13];
GLdouble pivotZ = viewMat[14];

glLoadMatrixd(cam2wld[cameraIndex].matrix());

glTranslated(pivotX, pivotY, pivotZ);
glRotated(deltaY, 1, 0, 0);
glTranslated(-pivotX, -pivotY, -pivotZ);

glMultMatrixd(wld2cam[cameraIndex].matrix());

If you want to do complex matrix operations, then I recommend to use a library like OpenGL Mathematics (GLM):

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
glm::dmat4 c2w = glm::make_mat4<double>(cam2wld[cameraIndex].matrix());
glm::dmat4 t   = glm::translate(glm::dmat4(1.0), glm::dvec3( deltaX, deltaY, 0.0));
glm::dmat4 w2c = glm::make_mat4<double>(wld2cam[cameraIndex].matrix());
glm::dmat4 o2w = glm::make_mat4<double>(obj2wld.matrix());

glm::dmat final = c2w * t * w2c * o2w;
glLoadMatrixd(glm::value_ptr(final));
Rabbid76
  • 142,694
  • 23
  • 71
  • 112
  • 1
    Like you said, I need to define the pivot and translate before rotating (I forgot to mention that I want the center of the rotation to be at the center of the modeling space). Thanks. – Noober Apr 23 '20 at 10:35