gpt4 book ai didi

c++ - 可变重力下的摄像机旋转和方向

转载 作者:太空宇宙 更新时间:2023-11-04 11:35:45 25 4
gpt4 key购买 nike

我正在尝试为第一人称的,基于鼠标外观的OpenGL实现相机 Controller 。当摄像机始终保持正常方向(摄像机向上 vector =世界Y轴)时,这是一个简单的问题。但是,我真的很难使用可以无缝地用于任何方向的相机正常工作。目的是允许玩家在整个星球上移动。另一个要求是,随着相机方向的变化,方向相对于方向保持相同。一个示例是,如果您绕着行星行走,则相对于地面的方向保持不变,因此当您从杆子的侧面“向下”走时,方向也会自动旋转。

到目前为止,我已经尝试了许多不同的方法来使此工作正常进行,但是正如我所看到的,应该有两种不同的方法来完成此工作。首先是根据来自世界轴的偏航角和俯仰角进行常规的相机旋转,然后通过相机方向转换结果的外观方向以获得最终的外观方向。第二种方法是基于计算的上,右 vector ,以偏航角和俯仰角旋转摄像机。向上 vector 在这里很容易;这只是方向。我没有找到正确的 vector ,尽管我发现它可以正常工作。

好的,这是这两种方法的代码。

通用代码

// m_orientation calculated from planet center to current position
m_horizontal += horizontal;
m_vertical += vertical;

while (m_horizontal > TWO_PI) {
m_horizontal -= TWO_PI;
}

while (m_horizontal < -TWO_PI) {
m_horizontal += TWO_PI;
}

if (m_vertical > MAX_VERTICAL) {
m_vertical = MAX_VERTICAL;
}
else if (m_vertical < -MAX_VERTICAL) {
m_vertical = -MAX_VERTICAL;
}

// code from either implementation

m_view = glm::lookAt(m_position, m_position + m_direction, m_orientation);

首先偏航,围绕世界坐标轴倾斜,然后进行变换
// check for m_orientation != WORLD_UP...
glm::vec3 axis = glm::normalize(glm::cross(WORLD_UP, m_orientation));
float angle_degrees = acosf(m_orientation.y) * RADS_TO_DEGREES;
glm::mat4 trans = glm::rotate(glm::mat4(), angle_degrees, axis);

// can also be determined with two rotation matrices about world axes, end result is identical
m_direction = glm::vec3(cosf(m_vertical) * sinf(m_horizontal),
sinf(m_vertical),
cosf(m_vertical) * cosf(m_horizontal));
m_direction = glm::vec3(trans * glm::vec4(m_direction));

关于适当的上下 vector 的偏航和俯仰的第二种方法
m_right = ??? // tried literally everything
glm::mat4 yaw = glm::rotate(glm::mat4(), m_horizontal, m_orientation);
glm::mat4 pitch = glm::rotate(glm::mat4(), m_vertical, m_right);
glm::mat4 trans = yaw * pitch;
m_direction = glm::vec3(trans[2]); // z axis

好的,这就是问题所在。第一种方法几乎可以完美工作,但是在行星南极附近(在〜15度方向=(0,-1,0)之内,效果越接近,效果越强),相机会自动向南极旋转方向改变。因此,如果摄像机方向不变,则在南极附近,摄像机将正常工作。方向的任何变化都将导致相机向南极旋转。方向变化越大,相机旋转得越多。现在,我尝试从世界轴相机旋转中删除俯仰或偏航,并且这种效果仅在包含俯仰计算时才出现。仅偏航,相机便表现完美(没有任何俯仰控制)。据我所知,我从常规up =(0,1,0)到当前方向的转换是错误的。有什么帮助吗?

现在,另一种做事方式似乎可以正确地工作,但是我只是没有找到合适的正确方法。我尝试过的所有操作都会导致水平和垂直运动的异常行为。最明显的解决方案是,前一帧的方向与当前方向的叉积不能生成正确的 vector 。有什么好的 vector 的建议吗?

我也很高兴看到针对此问题的完全不同的解决方案。我知道这是可能的,但是没有任何搜索能给我一个好的解决方案。首先十分感谢。

编辑1:针对PawełStawarz尝试了更多方法

导致相机方向错误和鼠标移动异常。我确保矩阵乘法的顺序正确。我也尝试过移调。
m_view = glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), m_direction, m_up);
m_view = trans * m_view; //trans is rotation from orientation=(0,1,0) to orientation=m_orientation

由于相机本身向南极旋转,因此导致与以前相同的问题。另外,垂直鼠标旋转不正确,会导致相机旋转。
m_view = glm::lookAt(glm::vec3(0.0f, 0.0f, 0.0f), m_direction, m_up);
m_view = trans * m_view;
m_direction = glm::vec3(m_view[2]);

m_view = glm::lookAt(m_position, m_direction + m_position, m_orientation);

编辑2:使用RIGHT vector 方法,方向之间没有任何转换会更好一些。但是,这会导致摄像机偏航角以接近垂直方向(与垂直方向至少5度)的角度剧烈摆动。另外,俯仰的运动范围不受方向的调节,因此例如在行星的侧面,垂直运动被限制为直接在您的前面到您的后面(〜(0,1,0)到〜 (0,-1,0))。
glm::mat4 yaw = glm::rotate(glm::mat4(), m_horizontal * ONEEIGHTY_PI, m_orientation);
glm::mat4 pitch = glm::rotate(glm::mat4(), m_vertical * -ONEEIGHTY_PI, m_right);

glm::mat4 cam = pitch * yaw;

m_right = glm::vec3(cam[0]);
m_up = glm::vec3(cam[1]);
m_direction = glm::vec3(cam[2]);

m_view = glm::lookAt(m_position, m_direction + m_position, m_up);
m_vp = m_perspective * m_view;

最佳答案

解决了。需要不同的转换。请参阅here,以获得很好的解释。

glm::mat4 trans;
float factor = 1.0f;
float real_vertical = vertical;
m_horizontal += horizontal;
m_vertical += vertical;

while (m_horizontal > TWO_PI) {
m_horizontal -= TWO_PI;
}

while (m_horizontal < -TWO_PI) {
m_horizontal += TWO_PI;
}

if (m_vertical > MAX_VERTICAL) {
m_vertical = MAX_VERTICAL;
}
else if (m_vertical < -MAX_VERTICAL) {
m_vertical = -MAX_VERTICAL;
}

glm::quat world_axes_rotation = glm::angleAxis(m_horizontal * ONEEIGHTY_PI, glm::vec3(0.0f, 1.0f, 0.0f));
world_axes_rotation = glm::normalize(world_axes_rotation);
world_axes_rotation = glm::rotate(world_axes_rotation, m_vertical * ONEEIGHTY_PI, glm::vec3(1.0f, 0.0f, 0.0f));

m_pole = glm::normalize(m_pole - glm::dot(m_orientation, m_pole) * m_orientation);

glm::mat4 local_transform;

local_transform[0] = glm::vec4(m_pole.x, m_pole.y, m_pole.z, 0.0f);
local_transform[1] = glm::vec4(m_orientation.x, m_orientation.y, m_orientation.z, 0.0f);
glm::vec3 tmp = glm::cross(m_pole, m_orientation);
local_transform[2] = glm::vec4(tmp.x, tmp.y, tmp.z, 0.0f);
local_transform[3] = glm::vec4(m_position.x, m_position.y, m_position.z, 1.0f);

world_axes_rotation = glm::normalize(world_axes_rotation);
m_view = local_transform * glm::mat4_cast(world_axes_rotation);
m_direction = -1.0f * glm::vec3(m_view[2]);
m_up = glm::vec3(m_view[1]);
m_right = glm::vec3(m_view[0]);

m_view = glm::inverse(m_view);

关于c++ - 可变重力下的摄像机旋转和方向,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23115441/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com