[英]Yaw, Pitch and roll to glm::rotate
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. 我一直试图弄清楚这几个小时,我根本无法想出一个解决方案:我想要实现的是将方向向量转换为3个
glm::rotation
调用。
I have a cylinder positioned at (0, 0, 0)
with a certain radius and height. 我有一个位于
(0, 0, 0)
的圆柱体,具有一定的半径和高度。 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): 使用Leap Motion SDK我正在执行工具跟踪,它给出了尖端位置和方向向量(表示为指向与尖端相同方向的单位向量):
Source: https://developer.leapmotion.com/documentation/skeletal/java/api/Leap.Pointable.html
资料来源: 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: 此外,可以使用以下SDK函数从该向量中提取
yaw
, pitch
和roll
:
/// 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. 在我的OpenGL渲染循环中,我每帧提取尖端位置以及方向向量。 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. 当我试图根据Leap的工具方向旋转圆柱体时会出现问题。 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. ...使用
modelMatrix
成为成员变量。
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. 我已经在OpenGL和一般情况下扫描了许多关于旋转主题的类似问题,但我不确定我的代码究竟是什么问题。
I guess that there is some misunderstanding of what we have and what we want to get. 我想对我们拥有的和我们想要得到的东西存在一些误解。
The case is that, the direction vector does not uniquely determines the orientation of the body in space. 情况是,方向矢量不能唯一地确定身体在空间中的方向。 To make this statement clear, let's get a closer look at how can the rotations be represented in 3D space.
为了使这个陈述清楚,让我们仔细看看如何在3D空间中表示旋转。
Rotations about the origin have three degrees of freedom. 关于原点的旋转具有三个自由度。 This means, that you need three independent parameters to uniquely specify the orientation of a body.
这意味着,您需要三个独立参数来唯一地指定正文的方向。 Exactly three, no more no less.
正好三个,不多也不少。 There is no matter what are they as far as none of them can't be expressed it terms of other.
无论他们是什么,只要他们都不能表达其他的条款。 A 3D rotation can be specified in a number of ways.
可以通过多种方式指定3D旋转。 The most usual methods are:
最常用的方法是:
Let's get a closer look to your problem. 让我们仔细看看你的问题。 You have a direction vector and you want to use it to determine orientation of the cylinder.
你有一个方向向量,你想用它来确定圆柱的方向。 Essentially, you have only two independent parameters, because the length of the direction vector does not matter (let it be a unit vector for simplicity).
基本上,您只有两个独立的参数,因为方向向量的长度无关紧要(为简单起见,它是一个单位向量)。 So you can't just get the rotation from a direction vector, because there would be one arbitrary parameter.
所以你不能只从方向向量得到旋转,因为会有一个任意参数。
It is just impossible to get three unknown independent parameters from the input that contain only two independent parameters. 只能从输入中获得三个未知的独立参数,这些参数只包含两个独立参数。 There is a need for some additional constraint.
需要一些额外的约束。 Usually it is an Up-vector .
通常它是向上矢量 。 The additional constraint transforms the three unknown independent parameters into dependent parameters.
附加约束将三个未知的独立参数转换为相关参数。
I'd advise you to use glm::orientation function that builds an orientation matrix from the input of a direction vector and an up-vector. 我建议你使用glm :: orientation函数,它从方向向量和向上向量的输入构建方向矩阵。
As for yaw, pitch and roll angles, that you get from the specified SDK functions. 至于从指定的SDK函数获得的偏航,俯仰和滚转角度。 This functions doesn't not work in a way you are trying to use them.
此功能不会以您尝试使用它们的方式工作。 You should specify an up-vector.
您应该指定向上矢量。 For example, let's consider, that the up-vector is the direction of the y axle.
例如,让我们考虑一下,向上矢量是y轴的方向。 This means, that the roll angle would be always zero.
这意味着,侧倾角始终为零。 You should calculate the yaw angle, just as you do it before.
您应该像以前一样计算偏航角度。 So:
所以:
float yaw = std::atan2(x, -z);
The pitch angle would be std::atan2(y, -z) , but in rotated frame, not in the original. 俯仰角度为std :: atan2(y,-z) ,但在旋转的框架中,不在原始角度。 You should consider the pitch angle as an arc-tangent of the ratio of the direction vector projection length onto the xz plane and its projection onto y axle.
您应该将俯仰角视为方向矢量投影长度与xz平面的比率及其在y轴上的投影的反正切。 I mean:
我的意思是:
float projectionLength = std::sqrt(x * x + z * z);
float pitch = std::atan2(y, projectionLength);
When you are constructing the transform matrix, you should first apply the rotation appropriate to the pitch angle, then the rotation appropriate to the yaw rotation and then the translation. 在构造变换矩阵时,应首先应用适合于俯仰角度的旋转,然后应用适合于偏航旋转的旋转,然后应用平移。
See this for more information about the Tait–Bryan angles 请参阅此有关泰特-布赖恩角度的更多信息
Also, you should be aware of the fact, that rotations are not commutative. 此外,您应该意识到旋转不是可交换的事实。 This means that you should perform rotations in a strict sequence.
这意味着您应该按严格的顺序执行旋转。 There are six possibilities of choosing the rotation axes for Tait–Bryan angles, that are called as conventions.
选择Tait-Bryan角度的旋转轴有六种可能性,称为约定。 These conventions depend on the axes about which the rotations are carried out.
这些约定取决于进行旋转的轴。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.