Arcball 相机表现异常

Arcball camera behaving oddly

我有点困惑。我需要帮助,我尝试实施弧球相机。我遵循的理论在这里: https://www.khronos.org/opengl/wiki/Object_Mouse_Trackball

它 "works" 除了它不像 Renderdoc 中的 arcball 相机:

我的:

Renderdoc

所以在我的游戏中,当你尝试旋转离屏幕中心太远时,旋转方向似乎与它应该旋转的方向相反

vec3 ScreenToArcSurface(vec2 pos)
{
    const float radius = 0.9f; // Controls the speed
    if(pos.x * pos.x + pos.y * pos.y >= (radius * radius) / 2.f - 0.00001)
    {
        // This is equal to (r^2 / 2) / (sqrt(x^2 + y^2)) since the magnitude of the
        // vector is sqrt(x^2 + y^2)
        return {pos, (radius * radius / 2.f) / (length(pos))};
    }

    return {pos.x, pos.y, sqrt(radius * radius - (pos.x * pos.x + pos.y * pos.y))};
}


void ArcballCamera::UpdateCameraAngles(void* ptr, glm::vec2 position, glm::vec2 offset)
{
    auto camera = reinterpret_cast<ArcballCamera*>(ptr);

    vec3 vb = ScreenToArcSurface(position);
    vec3 va = ScreenToArcSurface(position - offset);

    float angle = acos(glm::min(1.f, dot(vb, va)));
    vec3 axis = cross(va, vb);

    camera->rotation *= quat(cos(angle) / 2.f, sin(angle) * axis);
    camera->rotation = normalize(camera->rotation);
}

glm::mat4 ArcballCamera::GetViewMatrix()
{
    return glm::lookAt(
        look_at_point + rotation * (position - look_at_point),
        look_at_point,
        rotation * up);
}

我不明白我实现的和 khronos link 描述的有什么区别。

我把位置乘以-1来修复它;.

我不明白为什么这样可以解决数学问题。输入坐标是我所期望的。位置从 -1 归一化为 1,左上角是 (-,-) 右上角是 (+,-),左下角是 (-,+) 最后一个是 (+,+).

所以我不知道为什么我需要在负坐标系中工作才能工作。

问题是我从中获取的网站定义了 OpenGL 坐标系的公式。

但是我正在研究 vulkan,其中 Y 坐标被翻转,这改变了系统的惯用手性。因此,按原样使用公式会使用错误的一半球体。

Vulkan 的正确实现只需要否定 z 分量,即:

vec3 ScreenToArcSurface(vec2 pos)
{
    const float radius = 0.9f; // Controls the speed
    if(pos.x * pos.x + pos.y * pos.y >= (radius * radius) / 2.f - 0.00001)
    {
        // This is equal to (r^2 / 2) / (sqrt(x^2 + y^2)) since the magnitude of the
        // vector is sqrt(x^2 + y^2)
        return {pos, -(radius * radius / 2.f) / (length(pos))};
    }

    return {pos.x, pos.y, -sqrt(radius * radius - (pos.x * pos.x + pos.y * pos.y))};
}