GLM 从 vec3 制作旋转矩阵

Posted

技术标签:

【中文标题】GLM 从 vec3 制作旋转矩阵【英文标题】:GLM Make Rotation Matrix from vec3 【发布时间】:2015-12-19 02:30:54 【问题描述】:

我正在制作一款游戏,我需要弹丸朝向其前进的方向。我知道它的方向,我需要制作一个转换矩阵,使我可以将弹丸模型方向(1、0、0)或正 X 轴与任意向量对齐。我怎么能在 glm 中做到这一点?

【问题讨论】:

【参考方案1】:

你用什么来准确表示方向?

你可以这样做:

glm::mat4 transform = glm::eulerAngleYXZ(euler.y, euler.x, euler.z);

或者通过四元数:

glm::quat rot = glm::angleAxis(glm::radians(angle_in_degrees), glm::vec3(x, y, z));
glm::mat4 rotMatrix = glm::mat4_cast(rot);

除非您正在寻找像glm::lookAt 这样简单的东西?

detail::tmat4x4<T> glm::gtc::matrix_transform::lookAt   
(   
    detail::tvec3< T > const &  eye,     // from
    detail::tvec3< T > const &  center,  // to
    detail::tvec3< T > const &  up       // up
)

【讨论】:

非常感谢。愿你的日子充满繁荣。【参考方案2】:

嘿,我想出了答案,这与 @Mr_Pouet 很接近,但在这里:

const glm::vec3 a = ...;
const glm::vec3 b = ...; // in my case (1, 0, 0)
glm::vec3 v = glm::cross(b, a);
float angle = acos(glm::dot(b, a) / (glm::length(b) * glm::length(a)));
glm::mat4 rotmat = glm::rotate(angle, v);

您可以将 a 或 b 替换为您想要的任何内容,其中 a 是您要转换为的向量,b 是您所在的位置。如果 b 是 (1, 0, 0) 或 x 轴,我们可以优化它,就像我的例子一样:

glm::vec3 v = glm::vec3(0, -a.z, a.y);
float angle = acos(a.x / glm::length(a));
glm::mat4 rotmat = glm::rotate(angle, v);

我希望这对某人有帮助!

【讨论】:

【参考方案3】:

其他答案都不是真正完整的答案,因为它们不处理 cross(.,.)=0up||at-eye 等特殊情况。

这是一个相当完整的解决方案,应该适用于您不关心旋转对象的方向(即线或圆柱等)的所有情况:

glm::vec3 from;
glm::vec3 to;

glm::vec3 v = glm::cross(to, from);
float angle = acos(glm::dot(to, from) / (glm::length(to) * glm::length(from)));
glm::mat4 rotmat = glm::rotate(angle, v);

// special cases lead to NaN values in the rotation matrix
if (glm::any(glm::isnan(rotmat * glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)))) 
    if (angle < 0.1f) 
        rotmat = glm::mat4(1.0f);
    
    else if (angle > 3.1f) 
        // rotate about any perpendicular vector
        rotmat = glm::rotate(angle, glm::cross(from,
                                      glm::vec3(from.y, from.z, from.x)));
    
    else 
        assert(false);
    

此解决方案的另一个缺点是它非常“活泼”,即。特殊情况仅在矩阵爆炸时触发。在处理接近并行案例的案例时,这可能会导致伪影。通常,人们会希望在重叠区域之间转换并在每个区域中应用连续解决方案。为此,我猜最好分解成欧拉角。如果有人跳过任何此类算法,请发布。我的意思是,这对学生来说也是一份体面的家庭作业。

【讨论】:

以上是关于GLM 从 vec3 制作旋转矩阵的主要内容,如果未能解决你的问题,请参考以下文章

相机 旋转

相机 旋转

相机 旋转

GLM 旋转矩阵与预期结果不同

OpenGL制作物面相机

GLSL 中的正常旋转