旋转玩家模型以指向一个点
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 轴作为旋转轴以上是关于旋转玩家模型以指向一个点的主要内容,如果未能解决你的问题,请参考以下文章