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

Posted

技术标签:

【中文标题】旋转玩家模型以指向一个点【英文标题】:Rotating the player model to point towards a point 【发布时间】:2020-05-24 10:32:16 【问题描述】:

我看过三年前的帖子,问了一个类似的问题,关于如何使用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,那么你只需要定义一个向上向量(例如glm::vec3 upVector(0, 1, 0) 并且你可以使用glm::lookAt(position, targetPoint, upVector) 来定义一个视图矩阵。无论如何,目前还不清楚你试图实现什么。你想计算一个视图矩阵吗?观点是position?还是你想计算一个模型转换? 哦,是的,应该澄清一下!我想构建我的播放器对象的模型矩阵,然后我可以将其加载到我的模型加载中。所以我想我需要一个旋转变换矩阵。翻译部分工作得很好。 【参考方案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);

【讨论】:

我需要轴做什么?这难道不是 glm::rotate 所做的吗? oook,我不知道为什么它适用于您的代码而不适用于 glm::rotate,但我非常感谢。谢谢! @KonstiLackner 你的旋转矩阵只围绕y轴旋转glm::vec3(0.0, 1.0, 0.0)(左右),而不是上下(围绕x轴glm::vec3(1.0, 0.0, 0.0) 这就是为什么我给 glm::rotate y 轴作为旋转轴

以上是关于旋转玩家模型以指向一个点的主要内容,如果未能解决你的问题,请参考以下文章

如何在PaperJS中围绕鼠标旋转点?

如何旋转模型以跟随路径

OpenGL - 2D敌人不旋转面对玩家

C ++ / openGL:使用四元数将QUAD旋转到一个点

三维坐标旋转矩阵

相对于一个点旋转相机