0
\$\begingroup\$

Here's my code:

vec4 qx, qy, qz;
mat4 mx, my, mz;

// rotating using quaternions
glm_quat(qx, to_radians(a->rx), 1.0f, 0.0f, 0.0f);
glm_quat(qy, to_radians(a->ry), 0.0f, 1.0f, 0.0f);
glm_quat(qz, to_radians(a->rz), 0.0f, 0.0f, 1.0f);

// turning the quaternions into matrices
glm_quat_mat4(qx, mx);
glm_quat_mat4(qy, my);
glm_quat_mat4(qz, mz);

mat4 trans = {
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1 
};

mat4 rot = {
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1
};

mat4 final;

// combining the rotations into one.
glm_mat4_mulN((mat4* []){&mx, &my, &mz}, 3, rot);

// translating the `trans` matrix.
glm_translate(trans, (vec3){ a->x, a->y, a->z });

// finally combining the translation with the rotation into one.
glm_mat4_mul(trans, rot, final);

My desired behavior is that the object rotates around its center, but here is what happens instead: enter image description here

So , it seems that my object is rotating around some weird other undefined point. I have no idea why this happens.

Any ideas? Thank you.

\$\endgroup\$
  • \$\begingroup\$ You applied the rotation and translation in the wrong order. To rotate an object around its center its center has to be at the origin (0,0,0). Note that multiplication of matrices is not commutative. In general: A·B != B·A \$\endgroup\$ – Socowi Jun 7 at 10:29
  • \$\begingroup\$ @Socowi But when I change the order, then the Z axis becomes the Y axis, and my translation becomes messed up \$\endgroup\$ – Sebastian Karlsson Jun 7 at 10:31
0
\$\begingroup\$

Affine transformations use the following order:

  1. Translate
  2. Rotate
  3. Scale

I'm not sure what version of glm you are using, but the code looks very strange.

In C++ terms, it should look something like this:

// rotating using quaternions
glm::vec3 x(1.0f,.0f,.0f);
glm::vec3 y(.0f,1.0f,.0f);
glm::vec3 z(.0f,.0f,1.0f);

glm::quat q(1.0f);
q = glm::quat::rotate(q, x, to_radians(a->rx));
q = glm::quat::rotate(q, y, to_radians(a->ry));
q = glm::quat::rotate(q, z, to_radians(a->rz));

glm::mat4 ident(1.0f), final(1.0f);

glm::mat4 translate = glm::translate(ident, a->position);
glm::mat4 rotate = glm::toMat4(q); // Or something like that
glm::mat4 scale = glm::scale(glm::mat4(1.0f), a->scale);

final = scale * rotate * translate * ident; // In code order is right to left.

The above code is using the current glm API, so I can only assume you are either using a very old version, or are intentionally abstracting the actual glm calls. In any case:

  1. Order matters. To rotate around a point, rotate first, then translate. To rotate around the centre of the object translate first, then rotate: AB != BA. Read https://en.wikipedia.org/wiki/Affine_transformation for more information.

  2. Resource Acquisition Is Initialization(RAII): ALWAYS initialize your matrices to the identity matrix values: GLM matrices are internally an array of floats, so when assigned, will just use whatever data happens to be in that memory at the time. If you're lucky, it will be zeroed. Don't count on that. In fact, follow RAII best practices and always initialize all your variables. It might seem tedious, but I guarantee you, as your code gets more complex, uninitialized numerical data will account for more than half your weird, hard to explain behavior. Read https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization for more information.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.