旋转玩家模型以指向一个点
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);
我看到三年前的 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);