【问题标题】:Creating a First Person camera in Open GL 2.0 and glm在 Open GL 2.0 和 glm 中创建第一人称相机
【发布时间】:2012-08-21 01:11:46
【问题描述】:

我对 Open GL 和 c++ 非常陌生,并且遇到了创建第一人称相机的问题。我不懂矩阵数学,所以这对我来说更加困难。到目前为止,为了计算相机的旋转,我已经这样做了:

void CameraFP::calculate_view()  {
    m_view = glm::rotate(m_view, this->get_rotation_x(), glm::vec3(1, 0, 0));
    m_view = glm::rotate(m_view, this->get_rotation_y(), glm::vec3(0, 1, 0));
}

每次更新调用都会调用该函数。

为了通过鼠标处理相机的旋转,我做了以下操作:

void CameraFP::process_mouse(sf::Window *app)  {
    GLfloat mouse_x = app->GetInput().GetMouseX();
    GLfloat mouse_y = app->GetInput().GetMouseY();

    GLfloat mouse_x_delta = std::max(mouse_x, old_mouse_x) - std::min(mouse_x, old_mouse_x);
    GLfloat mouse_y_delta = std::max(mouse_y, old_mouse_y) - std::min(mouse_y, old_mouse_y);

    y_rot += mouse_x_delta / (float)app->GetWidth();
    x_rot += mouse_y_delta / (float)app->GetHeight();

    this->old_mouse_x = mouse_x;
    this->old_mouse_y = mouse_y;

    app->SetCursorPosition(app->GetWidth() / 2, app->GetHeight() / 2);
}

为了处理运动,我做了以下工作:

void CameraFP::process_keyboard(sf::Window *app)  {
    const sf::Input *input = &app->GetInput();

    if (input->IsKeyDown(sf::Key::W))  {
        position.z += 1.0f / 100.0f;
    }
    if (input->IsKeyDown(sf::Key::S))  {
        position.z -= 1.0f / 100.0f;
    }
    if (input->IsKeyDown(sf::Key::A))  {
        position.x -= 1.0f / 100.0f;
    }
    if (input->IsKeyDown(sf::Key::D))  {
        position.x += 1.0f / 100.0f;
    }
}

我的问题在于我的相机不会朝着您所面对的方向移动,并且它永远不会停止旋转:/。另外,如果你能给我指点关于矩阵数学的指南或其他东西,那就太棒了:)

编辑 2:'

我刚刚启动了一个新的进程鼠标功能,它沿着屏幕的 x 轴移动,作为相机正确的 y 旋转。但是,无论我向左还是向右移动鼠标都没有关系,这两个动作都会使我向右旋转。与 3d 空间中的 x 轴相同,但这发生在向下。关于造成这种情况的任何想法?

void CameraFP::process_mouse(sf::Window *app)  {
    GLfloat mouse_x = app->GetInput().GetMouseX();
    GLfloat mouse_y = app->GetInput().GetMouseY();

    GLfloat mouse_x_delta = old_mouse_x - mouse_x;
    GLfloat mouse_y_delta = old_mouse_y - mouse_y;

    if (mouse_x_delta > 0)  {
        y_rot += mouse_x_delta / (float)app->GetWidth() * 0.1f;
    } else if (mouse_x_delta < 0)  {
        y_rot -= mouse_x_delta / (float)app->GetWidth() * 0.1f;
    }
    if (mouse_y_delta > 0)  {
        x_rot += mouse_y_delta / (float)app->GetWidth() * 0.1f;
    } else if (mouse_y_delta < 0)  {
        x_rot -= mouse_y_delta / (float)app->GetWidth() * 0.1f;
    }


    if (mouse_x != old_mouse_x)  {
        m_view = glm::rotate(m_view, y_rot, glm::vec3(0, 1, 0));
    }
    if (mouse_y != old_mouse_y)  {
        m_view = glm::rotate(m_view, x_rot, glm::vec3(1, 0, 0));
    }

    this->old_mouse_x = mouse_x;
    this->old_mouse_y = mouse_y;

    app->SetCursorPosition(app->GetWidth() / 2, app->GetHeight() / 2);
}

【问题讨论】:

  • 一些提示:在应用绝对旋转之前将您的视图矩阵重置为恒等;矩阵之间的乘法不可交换,因此参数的顺序很重要。 Here你可以找到更多信息。
  • @Gigi 很棒的资源,非常感谢! :)

标签: c++ opengl matrix glm-math


【解决方案1】:

目前我没有时间查找我的相机代码,但我现在可以告诉你的是,你的运动计算完全错误。
你没有考虑相机旋转. 你必须这样做:

if (input->IsKeyDown(sf::Key::W))  {
    position.z += sin(camera_rot_y);
}
else if (input->IsKeyDown(sf::Key::S))  {
    position.z -=  sin(camera_rot_y);
}

if (input->IsKeyDown(sf::Key::A))  {
    position.x -=  cos(camera_rot_y);
}
else if (input->IsKeyDown(sf::Key::D))  {
    position.x +=  cos(camera_rot_y);
}

你也可以使用“else if”,因为你不能同时向前和向后移动。^^

另外,你为什么在下面的代码中使用 std::min() 和 max() ?:

GLfloat mouse_x_delta = std::max(mouse_x, old_mouse_x) - std::min(mouse_x, old_mouse_x);
GLfloat mouse_y_delta = std::max(mouse_y, old_mouse_y) - std::min(mouse_y, old_mouse_y);

如果你想在相反的方向旋转,你需要得到一个负的增量,这在你的代码中是不可能的。摆脱 min() 和 max() 函数。

顺便说一句:我的相机代码不是最有效的(使用旋转而不是直接计算),但它可以工作。

【讨论】:

    【解决方案2】:

    您没有在CameraFPm_view 中显示position 的用法,但我认为这里有问题:

    void CameraFP::process_keyboard(sf::Window *app)  {
        const sf::Input *input = &app->GetInput();
    
        if (input->IsKeyDown(sf::Key::W))  {
            position.z += 1.0f / 100.0f;
        }
        if (input->IsKeyDown(sf::Key::S))  {
            position.z -= 1.0f / 100.0f;
        }
        if (input->IsKeyDown(sf::Key::A))  {
            position.x -= 1.0f / 100.0f;
        }
        if (input->IsKeyDown(sf::Key::D))  {
            position.x += 1.0f / 100.0f;
        }
    }
    

    你必须用这个翻译乘以矩阵和m_view。在矩阵乘法中,矩阵的重要顺序。首先必须是m_view,因为它是主矩阵,并且您想从m_view 旋转向前移动。但是有glm 命名空间和glm::translate 方法,它们以正确的顺序相乘,您只需创建glm::vec3 作为该方法的参数(用x、y、z 翻译)。

    (如果您使用相对位置 ...仅帧之间的差异)

    所以你必须像这样改变它:

    void CameraFP::process_keyboard(sf::Window *app)  {
        const sf::Input *input = &app->GetInput();
    
        glm::vec3 pos;
        if (input->IsKeyDown(sf::Key::W))  {
            pos.z += 1.0f / 100.0f;
        }
        if (input->IsKeyDown(sf::Key::S))  {
            pos.z -= 1.0f / 100.0f;
        }
        if (input->IsKeyDown(sf::Key::A))  {
            pos.x -= 1.0f / 100.0f;
        }
        if (input->IsKeyDown(sf::Key::D))  {
            pos.x += 1.0f / 100.0f;
        }
    
        //Make translation
        m_view = glm::translate(m_view, pos);
    
        //Values at position 12, 13, 14 are translation x, y, z
        //Save absolute position of camera
        position = glm::vec3(m_view[12], m_view[13], m_view[14]);
    
    }
    

    PS:对不起我的英语不好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多