How to apply/search for global/local transformations in Opengl

Asked

Viewed 445 times

5

I am programming a simple Game Engine using the graphical API Opengl. But I have a problem that I can’t solve. The problem is that the transformations in world (world) do not work properly. The scale transformations are normal, but the translation and rotation which are the problem.

For example, if I move the camera locally and then rotate it globally on the Y axis (the axis that points up) and locally on the X axis (a simple mouse look), the camera starts rotating as a pivot having its source center where it was created.

Each Engine object/entity has a base class HTransform, which serves to rotate/move/stagger global/local (local, along its own axis). And I had a function to update the transformation matrix. After the transformations are done I apply the matrix m_WorldTransform. In the matrix of the camera I use the glLoadMatrixf, and on objects glMultMatrixf.

// C++ - Resumo da classe HTransform

void setWorldPosition(const HVec3f& pos);
Hvec3f getWorldPosition() const;
// Ect......

HVec3f m_WorldPosition;
HQuaternion m_WorldOrientation;
HVec3f m_WorldScaling;

HVec3f m_LocalPosition;
HQuaternion m_LocalOrientation;
HVec3f m_LocalScaling;

HMatrix4 m_WorldTransform;
HMatrix4 m_LocalTransform;

void HTransform::updateTransform()
{
    m_WorldTransform.setRotationAxis(m_WorldOrientation.getAngle(), m_WorldOrientation.getAxis());
    m_WorldTransform.translate(m_WorldPosition);
    m_WorldTransform.scale(m_WorldScaling);

    m_LocalTransform.setRotationAxis(m_LocalOrientation.getAngle(), m_LocalOrientation.getAxis());
    m_LocalTransform.translate(m_LocalPosition);
    m_LocalTransform.scale(m_LocalScaling);

    m_WorldTransform = m_WorldTransform * m_LocalTransform;// * m_WorldTransform.getInverse();

    m_NeedTransformUpdate = false;
}

The camera also has the base class HTransform.

// C++ - Resumo da classe HCamera
HMatrix4 m_MatView;
HMatrix4 m_MatProjection;

void HeCamera::updateViewMatrix()
{
    //this->updateTransform();

    m_WorldTransform.setRotationAxis(m_WorldOrientation.getAngle(), m_WorldOrientation.getAxis());
    m_WorldTransform.translate(m_WorldPosition);
    m_WorldTransform.scale(m_WorldScaling);

    m_LocalTransform.setRotationAxis(m_LocalOrientation.getAngle(), m_LocalOrientation.getAxis());
    m_LocalTransform.translate(m_LocalPosition);
    m_LocalTransform.scale(m_LocalScaling);

    m_WorldTransform = m_WorldTransform * m_LocalTransform;

    m_MatView = m_WorldTransform.invert();
    m_NeedTransformUpdate = false;
}

As you can see each Object/entity will use two matrices, one for global transformations and one for local transformations. But I wanted to use it for just one, but I don’t know how to do it.

I did the upload a demo to better visualize the problem. The controls are W, A, S, D, Q and E for the movements and the mouse to control the orientation of the camera (a Mouselook).

The demo contains a file script_test.lua that from line 75, is the part that controls the orientation/rotation of the camera.

What am I doing wrong?

1 answer

2

At first glance, there is a particularity in the order in which you are applying two transformations:

m_WorldTransform.Translate(m_WorldPosition);

m_WorldTransform.Scale(m_WorldScaling);

If you move first, and resize later, the translation will end up being affected by resizing. For example, if you move +10 on the X-axis, and then resize the X-axis by 0.5, you will effectively halve the size of the X-axis object, and move only +5 in the direction of the X-axis.

This is because all transformations take as their basis the origin of space (0, 0, 0). The same occurs with rotation, and all other linear transformations.

If you want to test these transformations, and have a web browser that supports Webgl, you can use an online interactive material that I make available to my college students: Webgl - Matrices and Linear Transformations.

Take the following test:

Create a translation (10, 0, 0), then add a resize (50%, 100% 100%). Select the last item from the list and click "Animate step by step". Then reverse the translation and resizing order, select the last item from the list and click "Animate step by step".

With this you can feel the difference visually.

  • Legal the material of the link. Very useful.

  • Thanks! If you find a bug, let me know ;)

  • I understood, but if I do this the objects will not undergo transformation along their own axis (local). You may notice that in the demo I posted, just when the object (a cube) is opened, it is already rotated 45º on its global axis Y and with a scale of 3 on its local axis X (I took the test). It’s in line 28 and 29 of the script that accompanies the demo.

  • The difference between local and global, it’s just that everything local, mathematically applied before it’s global. Running the code, I think I understand your question better. You would like the camera not only to walk along the X, Y and Z axes, but to walk in the direction that the camera is "looking", right? Like a person walking in a park, I got it right?

  • Exactly, but not just the camera, for any object/entity that uses the class HTransform (which is the class responsible transformations). It possesses the methods setWorldOrientation and setLocalOrientation, that are for global/local transformations. But I’ve been researching this for a long time and I can’t find an answer :/. But you looked at the demo just to better understand what’s going on?

  • It is because this "orientation" is just another way of saying "rotation matrix". In order for the object/camera to move in the direction it is "looking", you need to manually apply the rotation of the angle of its orientation to the parameters used as the movement delta. For example, assuming the object has a $ rotation on the Y axis, then at the time of moving you should not ask it to move (dx, dy, dz), but yes (dx * cos($), dy, dz * sin($)) (may need to switch to -sin and/or -cos depending on your coordinate system).

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.