方向向量转旋转矩阵

18

如何从方向(单位向量)创建旋转矩阵

我的矩阵是3x3的,列主序,右手坐标系

我知道'column1'表示右方向,'column2'表示上方向,'column3'表示前方向

但我不会做到这一点。

//3x3, Right Hand
struct Mat3x3
{
    Vec3 column1;
    Vec3 column2;
    Vec3 column3;

    void makeRotationDir(const Vec3& direction)
    {
        //:((
    }
}

1
对于一个旋转矩阵,你需要一个方向向量(例如一个轴)一个角度。如果只给出一个方向,你在谈论什么样的旋转? - 6502
我想要做这个: Vec3 dirToEnemy = (Enemy.Position - Player.Position).normalize(); Player.Matrix.makeRotationDir(dir); Player.Attack(); - UfnCod3r
1
@6502:不,对于旋转矩阵,你也可以使用三个向量(x、y、z)。 - SigTerm
@SigTerm:当然可以自由定义一个函数,给它你喜欢的任何东西(包括宠物狗的名字),返回一个旋转值,这并不违法,也不会让你坐牢。但是从维度上来看,即使是三个满足 x^2+y^2+z^2=1 的实数也不足够(原点周围的旋转数量比单位球面上的点还要多)。 - 6502
1
@6502: 3 向量,每个向量有3个分量,定义了局部坐标系(x、y、z轴)在全局坐标系中的位置,这将形成一个3x3的旋转矩阵。您也可以使用欧拉角进行旋转。或者使用3个点。或四元数。 - SigTerm
@SigTerm:三个向量或三个点(9个分量)对于规范来说太多了,也不是问题所要求的(其中指定了一个长度为1的单一方向)。我认为你在评论中只是打错了字。 - 6502
2个回答

21
struct Mat3x3
{
    Vec3 column1;
    Vec3 column2;
    Vec3 column3;

    void makeRotationDir(const Vec3& direction, const Vec3& up = Vec3(0,1,0))
    {
        Vec3 xaxis = Vec3::Cross(up, direction);
        xaxis.normalizeFast();

        Vec3 yaxis = Vec3::Cross(direction, xaxis);
        yaxis.normalizeFast();

        column1.x = xaxis.x;
        column1.y = yaxis.x;
        column1.z = direction.x;

        column2.x = xaxis.y;
        column2.y = yaxis.y;
        column2.z = direction.y;

        column3.x = xaxis.z;
        column3.y = yaxis.z;
        column3.z = direction.z;
    }
}

1
那么如果方向对应向上,则不会应用旋转? - Viktor Sehr

4
要完成您在评论中想要做的事情,您还需要知道您的玩家之前的方向。实际上,最好的方法是将有关玩家位置和方向(以及游戏中几乎所有其他内容)的所有数据存储在一个4x4矩阵中。通过向3x3旋转矩阵添加第四列和第四行,并使用额外的列来存储关于玩家位置的信息来实现此目的。这背后的数学(齐次坐标)相当简单,在OpenGL和DirectX中非常重要。我建议您参考这个很棒的教程:http://www.opengl-tutorial.org/beginners-tutorials/tutorial-3-matrices/。现在,使用GLM将您的玩家旋转到敌人位置,可以这样做:
1)在您的玩家和敌人类中,声明一个矩阵和3d向量来表示位置。
glm::mat4 matrix;
glm::vec3 position;

2) 朝敌人旋转

player.matrix =  glm::LookAt(
player.position, // position of the player
enemy.position,   // position of the enemy
vec3(0.0f,1.0f,0.0f) );        // the up direction 

3) 要将敌人朝向玩家旋转,执行以下操作:

enemy.matrix =  glm::LookAt(
enemy.position, // position of the player
player.position,   // position of the enemy
vec3(0.0f,1.0f,0.0f) );        // the up direction 

如果您想将所有内容存储在矩阵中,不要将位置声明为变量,而应声明为函数。
vec3 position(){
    return vec3(matrix[3][0],matrix[3][1],matrix[3][2])
}

并旋转

player.matrix =  glm::LookAt(
player.position(), // position of the player
enemy.position(),   // position of the enemy
vec3(0.0f,1.0f,0.0f) );        // the up direction 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接