I've been trying to figure out this for hours now and I simply cannot come up with a solution for this: What I'm trying to achieve is transforming an orientation vector into 3 glm::rotation
calls.
I have a cylinder positioned at (0, 0, 0)
with a certain radius and height. With the Leap Motion SDK I'm performing tool tracking that gives me the tip position and a direction vector (that is expressed as a unit vector pointing in the same direction as the tip):
Source: https://developer.leapmotion.com/documentation/skeletal/java/api/Leap.Pointable.html
Furthermore, yaw
, pitch
and roll
can be extracted form that vector using the following SDK functions:
/// The yaw angle in radians.
///
/// Yaw is the angle between the negative z-axis and the projection of
/// the vector onto the x-z plane. In other words, yaw represents rotation
/// around the y-axis. If the vector points to the right of the negative z-axis,
/// then the returned angle is between 0 and pi radians (180 degrees);
/// if it points to the left, the angle is between 0 and -pi radians.
///
/// \image html images/Math_Yaw_Angle.png
///
/// @returns The angle of this vector to the right or left of the negative z-axis.
float yaw() const
{
return std::atan2(x, -z);
}
/// The pitch angle in radians.
///
/// Pitch is the angle between the negative z-axis and the projection of
/// the vector onto the y-z plane. In other words, pitch represents rotation
/// around the x-axis.
/// If the vector points upward, the returned angle is between 0 and pi radians
/// (180 degrees); if it points downward, the angle is between 0 and -pi radians.
///
/// \image html images/Math_Pitch_Angle.png
///
/// @returns The angle of this vector above or below the horizon (x-z plane).
float pitch() const {
return std::atan2(y, -z);
}
/// The roll angle in radians.
///
/// Roll is the angle between the negative y-axis and the projection of
/// the vector onto the x-y plane. In other words, roll represents rotation
/// around the z-axis. If the vector points to the left of the negative y-axis,
/// then the returned angle is between 0 and pi radians (180 degrees);
/// if it points to the right, the angle is between 0 and -pi radians.
///
/// \image html images/Math_Roll_Angle.png
///
/// Use this function to get roll angle of the plane to which this vector is a
/// normal. For example, if this vector represents the normal to the palm,
/// then this function returns the tilt or roll of the palm plane compared
/// to the horizontal (x-z) plane.
///
/// @returns The angle of this vector to the right or left of the y-axis.
float roll() const {
return std::atan2(x, -y);
}
In my OpenGL rendering loop, I'm extracting the tip position as well as the direction vector every frame. I'm passing the model matrix as a uniform variable to my shaders in the following way:
cylinder->ResetModelMatrix(); // Set model matrix to identity
glm::vec3 translation = glm::vec3(toolTipPosition.x, toolTipPosition.y, toolTipPosition.z);
cylinder->TranslateModel(translation);
cylinderProgram->SetUniform("modelMatrix", cylinder->GetModelMatrix());
With only the translation, this works nicely and looks something like this (with the cylinder always pointing up):
The problem occurs when I'm trying to rotate the cylinder according to the Leap's tool orientation. I have the following code:
yaw = toolDirection.yaw() * Leap::RAD_TO_DEG;
// similarly for pitch and roll
cylinder->Rotate(yaw, glm::vec3(0.0f, 1.0f, 0.0f));
// pitch around (1, 0, 0) and roll around (0, 0, 1)
However, I'm not getting the proper orientations and the cylinder is "flickering" and jumping between a lot of orientations when I try to apply this.
The important transformation functions are located in an interface from which my cylinder class is inheriting...
void Drawable::ResetModelMatrix()
{
this->modelMatrix = glm::mat4(1.0f);
}
void Drawable::TranslateModel(glm::vec3 translationVector)
{
this->modelMatrix = glm::translate(this->modelMatrix, translationVector);
}
void Drawable::RotateModel(float angle_in_degrees, glm::vec3 axisOfRotation)
{
this->modelMatrix = glm::rotate(this->modelMatrix, angle_in_degrees, axisOfRotation);
}
void Drawable::ScaleModel(glm::vec3 scalingVector)
{
this->modelMatrix = glm::scale(this->modelMatrix, scalingVector);
}
...with modelMatrix
beeing a member variable.
I've scanned a lot of similar questions on the topic of rotation in OpenGL and in general, but I'm not really sure what's exactly the problem with my code here.