【问题标题】:Move model in OpenGL by translate matrix instead of glTranslate()通过平移矩阵而不是 glTranslate() 在 OpenGL 中移动模型
【发布时间】:2019-02-13 11:53:39
【问题描述】:

我的目标是按箭头键移动对象。为此,在回调中,我从某个偏移量创建平移矩阵并将其乘以世界矩阵。但是它不起作用 - 立方体不会通过按键移动。我还注意到直接使用带有设置偏移量的 glTranslate() 效果很好,但看起来像拐杖。我的意思是,对于模型的任何转换,我都应该只使用转换矩阵。 我的代码中的问题在哪里?如何解决?为什么 glTranslate() 效果很好? 最小代码示例:


glm::mat4 mWorldMatrix;
glm::mat4 mViewMatrix;
glm::mat4 mProjMatrix;

void onKeyCallback(GLFWwindow*, int key, int scan, int action, int mods)
{
    switch (key)
    {
        case GLFW_KEY_UP:
        {
            auto translationMatrix = glm::translate(glm::mat4{}, glm::vec3{ 0, 1, 0 });
            mWorldMatrix = mWorldMatrix * translationMatrix;
            break;
        }
        case GLFW_KEY_DOWN:
        {
            auto translationMatrix = glm::translate(glm::mat4{}, glm::vec3{ 0, -1, 0 });
            mWorldMatrix = mWorldMatrix * translationMatrix;
            break;
        }
        case GLFW_KEY_LEFT:
        {
            auto translationMatrix = glm::translate(glm::mat4{}, glm::vec3{ -1, 0, 0 });
            mWorldMatrix = mWorldMatrix * translationMatrix;
            break;
        }
        case GLFW_KEY_RIGHT:
        {
            auto translationMatrix = glm::translate(glm::mat4{}, glm::vec3{ 1, 0, 0 });
            mWorldMatrix = mWorldMatrix * translationMatrix;
            break;
        }
    }
}


int main()
{
    glfwInit();

    const int weight = 640;
    const int height = 480;
    auto mWindow = glfwCreateWindow(weight, height, "TesT", nullptr, nullptr);
    glfwMakeContextCurrent(mWindow);

    glShadeModel(GL_SMOOTH);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);

    mWorldMatrix = glm::mat4{ 1.0f };
    mViewMatrix = glm::lookAt(glm::vec3{ 0, 0, -1 },
                              glm::vec3{ 0, 0, 0 },
                              glm::vec3{ 0, 1, 0 });
    mProjMatrix = glm::perspective(glm::radians(45.0f),
                                   static_cast<float>(weight) / height, 
                                   0.1f, 
                                   100.0f);

    glfwSetKeyCallback(mWindow, onKeyCallback);

    while (!glfwWindowShouldClose(mWindow)) {
        glClearColor(0.5, 0.5, 0.5, 0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glViewport(0,0, weight, height);

        auto modelViewMatrix = mViewMatrix * mWorldMatrix;
        glMatrixMode(GL_MODELVIEW);
        glLoadMatrixf(static_cast<const float*>(glm::value_ptr(modelViewMatrix)));

        glMatrixMode(GL_PROJECTION_MATRIX);
        glLoadMatrixf(static_cast<const float*>(glm::value_ptr(mProjMatrix)));

        Cube cube{ glm::vec3{0.5, 0.5, 0.5}, 1 }; //cube with center in {0.5} and side length 1
        auto vertices = cube.soup(); //vector of vertex

        glTranslatef(0 /* + offset.x*/, 0/* + offset.y*/, -5); //Setting offset here is work good
        glBegin(GL_TRIANGLES);
        for (const auto& vertex : vertices)
        {
            glColor3f(vertex.position.x, vertex.position.y, vertex.position.z);
            glVertex3f(vertex.position.x, vertex.position.y, vertex.position.z);
        }
        glEnd();

        glfwSwapBuffers(mWindow);
        glfwWaitEvents();
    }

    glfwTerminate();
    return 0;
}

【问题讨论】:

  • 您是否错过了将矩阵应用于顶点位置的步骤?您每次都重新初始化顶点,但不要应用您的可变矩阵

标签: c++ opengl graphics


【解决方案1】:

注意,由glBegin/glEnd 序列和固定函数矩阵堆栈和固定函数绘制。请参阅 Fixed Function PipelineLegacy OpenGL。 阅读Vertex SpecificationShader,了解最先进的渲染方式。


应该将投影矩阵应用于投影矩阵堆栈,并将模型视图矩阵应用于模型视图矩阵堆栈。

有 2 个问题。

  1. GL_PROJECTION_MATRIX 不是glMatrixMode 的有效枚举常量,将导致GL_INVALID_ENUM 错误。投影矩阵模式的有效枚举常量是GL_PROJECTIONGL_PROJECTION_MATRIX 将用于读取glGetFloatv 的当前投影矩阵。

  2. 如果你想对模型应用额外的变换,那么你必须在之前选择GL_MODELVIEW矩阵。如果GL_PROJECTION 矩阵被“选中”,则此状态将一直保持,直到再次显式更改。

glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(static_cast<const float*>(glm::value_ptr(modelViewMatrix)));

glMatrixMode(GL_PROJECTION); // <----- `GL_PROJECTION` instead of `GL_PROJECTION_MATRIX`
glLoadMatrixf(static_cast<const float*>(glm::value_ptr(mProjMatrix)));

// [...]

glMatrixMode(GL_MODELVIEW); // <-------- specify `GL_MODELVIEW`
glTranslatef(0 /* + offset.x*/, 0/* + offset.y*/, -5); //Setting offset here is work good

【讨论】:

    【解决方案2】:

    因为在每个循环中,您都将立方体设置到原始位置。您应该在循环之外定义这些对象。然后你可以在 while 循环中改变它们。

    在大学的 openGL 课程中,我大量使用了来自“The Cherno”的 youtube 系列。他发了openGL course

    【讨论】:

      猜你喜欢
      • 2012-06-01
      • 1970-01-01
      • 2012-05-05
      • 2014-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多