旋转玩家模型以指向一个点

Rotating the player model to point towards a point

我看到三年前的 post 问了一个有点类似的问题,关于如何用 glm::lookAt 实现这个,但不能完全应用到我的游戏中。

我有一个在曲线上移动的相机和播放器模型。这是通过计算曲线上的点并简单地用 glm::translate (identityMatrix, positionCameraIsCurrentlyAt) 将玩家移动到那里来完成的,因此我在曲线上有一个当前位置,还有一个 nextPosition。 我现在想使用变换矩阵旋转模型,但似乎无法完成。我的第一个想法是计算一个向量 currentPosition - nextPosition 以获得我应该面对的向量,我称之为 targetPoint。并通过简单地将其设置为 (0, 0, 1) 来计算我当前面临的向量以进行启动(当您看向负 z 时,我想这就是模型的方向)并将其更新为 targetPoint 向量旋转后。 顺便说一下,Bot 向量被归一化了。

代码如下所示:

glm::vec3 targetPoint = glm::normalize(position - curveIter->calcCurvePosition(curveProgress));
glm::mat4 rotationMatrix = glm::rotate(modelMatrix, glm::radians(glm::angle(pointingTowards, targetPoint)), glm::vec3(0.0, 1.0, 0.0));
glm::mat4 translationMatrix = glm::translate(modelMatrix, position);

// Test print vectors and angle 
std::cout << targetPoint.x << ", " << targetPoint.y << ", " << targetPoint.z << ", " << "pointing towards: " << pointingTowards.x << ", " <<pointingTowards.y << ", " << pointingTowards.z << ", " << glm::angle(glm::normalize(pointingTowards), forward) << std::endl;
pointingTowards = targetPoint;

// Test print vectors and angle 
std::cout << targetPoint.x << ", " << targetPoint.y << ", " << targetPoint.z << ", " << "pointing towards: " << pointingTowards.x << ", " << pointingTowards.y << ", " << pointingTowards.z << ", " << glm::angle(glm::normalize(pointingTowards), forward) << std::endl;

return translationMatrix*rotationMatrix;

这根本没有真正旋转模型。我打印了矢量和角度来检查它们和结果:

targetPoint: (-0.97509, 0, 0.22181)

pointingTowards: (-0.97509, 0, 0.22181)

angle: 3.14159

所以看起来它们都太小了。我想,这可能是归一化造成的……但是,该方法表示两个向量都需要归一化。 angle 始终是 Pi,这可能看起来很奇怪,但这是因为曲线是一个圆。显然,第一个 angle 是 2.35469,这是不正确的,因为向量是 targetPoint(-0.708167, 0, 0.706045) 和 pointingTowards: (0, 0, 1)分别。

知道我做错了什么吗? 非常感谢!

假设您有一个 position 和一个 targetPoint。您可以定义一个 upVec 并通过 Cross product 计算旋转矩阵的轴,如下所示:

glm::vec3 upVec(0, 1, 0);

glm::vec3 z_axis = glm::normalize(targetPoint - position);
glm::vec3 x_axis = glm::normalize(glm::cross(upVec, z_axis));
glm::vec3 y_axis = glm::normalize(glm::cross(z_axis, x_axis));

glm::mat4 rotationMatrix(
    glm::vec4(x_axis, 0),
    glm::vec4(y_axis, 0),
    glm::vec4(z_axis, 0),
    glm::vec4(0, 0, 0, 1));

另一种可能性是使用 Quaternion

#include <glm/gtx/quaternion.hpp>

定义从 (0, 0, 1) 到 tragetVec 的旋转并将四元数转换为旋转矩阵:

glm::vec3 tragetVec = glm::normalize(targetPoint - position);
glm::quat rotQuat = glm::rotation(glm::vec3(0, 0, 1), tragetVec);
rotationMatrix = glm::toMat4(rotQuat);