I want to rotate my car by 90 degrees to the left in the game I have.
When I use this code:
glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z);
glm::quat done(glm::rotate(rot,glm::eulerAngles(rot)+glm::vec3(90.0f,0.0,0.0)));
info.Rotation.x = done.x;
info.Rotation.y = done.y;
info.Rotation.z = done.z;
info.Rotation.w = done.w;
The car gets a weird rotation.
However the following codes doesn't change the cars rotation at all (just what I expected, just to be sure that GLM is compatible with the quats from the game):
glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z);
glm::quat done(rot);
info.Rotation.x = done.x;
info.Rotation.y = done.y;
info.Rotation.z = done.z;
info.Rotation.w = done.w;
and whenever I try this to check if the rotation is changed with it:
glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z);
glm::quat done(glm::rotate(rot,vec3(0.0,0.0,0.0)));
info.Rotation.x = done.x;
info.Rotation.y = done.y;
info.Rotation.z = done.z;
info.Rotation.w = done.w;
the cars rotation is just set to the 0,0,0,0 rotations in the game. I expected the rotations to remain untouched with this code because I expected the following code to rotate the car by 90 degrees left:
glm::quat rot(info.Rotation.w,info.Rotation.x,info.Rotation.y,info.Rotation.z);
glm::quat done(glm::rotate(rot,vec3(90.0,0.0,0.0)));
info.Rotation.x = done.x;
info.Rotation.y = done.y;
info.Rotation.z = done.z;
info.Rotation.w = done.w;
but that doesn't work the way I want. It just Sets the rotation, not adds it to 'rot'.
What am I doing wrong?
[While this isn't GLM, the ordering of quaternions in the multiply is still pretty clear, and that's usually the problem]
I've used code like this to avoid gimbal lock (since any solution introducing gimbal lock into code that already has quaternions is just too ironic to consider).
This is C code, and the QuaternionFromAngles() and QuaternionMultiply() are overwriting the target of the first parameter. world->axis6_input_rotation
is just a Quaternionf_t. The input is from a 6-axis controller, which is a bit more free form that your vehicle sim unless you're actually passing vectors around in your code.
typedef struct { float w, x, y, z; } Quaternionf_t;
void GuiMotion6axis(World_t *world, Port_t *port,
int x, int y, int z,
int xr, int yr, int zr)
{
// convert spaceball input to World->rotation (a quaternion)
// Source http://www.euclideanspace.com/maths/geometry/rotations/conversions/eulerToQuaternion/index.htm
const float scale = 0.0004; // should factor in the time delta it covers as well.
float xrf = (float)xr * scale;
float yrf = (float)yr * scale;
float zrf = (float)zr * scale;
QuaternionFromAngles(& world->axis6_input_rotation, xrf, yrf, zrf);
QuaternionMultiply(& world->rotation, // worldrot = inputrot * worldrot
& world->axis6_input_rotation, // a read-only use
& world->rotation // a read-only use
);
world->position.x += (float)x * scale; // really should factor in the
world->position.y += (float)y * scale; // elasped time.
world->position.z += (float)z * scale;
return;
}