GLM从vec3制作旋转矩阵

时间:2015-12-19 02:30:54

标签: c++ matrix axis rotational-matrices glm-math

我正在制作一个游戏,我需要射弹来面对它的方向。我知道它的方向,我需要制作一个转换矩阵,允许我将射弹模型方向(1,0,0)或正X轴与任意向量对齐。我怎么能用glm做到这一点?

3 个答案:

答案 0 :(得分:3)

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

你可以这样做:

public class Example extends JFrame {

public static final int WIDTH = 550;//Any Size
public static final int HEIGHT = 335;//Any Size

public Example(){

      init();

}

private void init() {

    try {
        UIManager
                .setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");

        SwingUtilities.updateComponentTreeUI(this);
        Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
        setSize(WIDTH, HEIGHT);

        setLocation((int) (dimension.getWidth() / 2 - WIDTH / 2),
                (int) (dimension.getHeight() / 2 - HEIGHT / 2));


    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (UnsupportedLookAndFeelException e) {
        e.printStackTrace();
    }

}
}

或通过四元数:

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

答案 1 :(得分:3)

嘿,我想出了答案,接近@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);

我希望这有助于某人!

答案 2 :(得分:0)

其他答案都不是真正完整的答案,因为它们没有处理 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);
    }
}

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