簡體   English   中英

如何在Opengl中圍繞世界軸而不是局部軸旋轉對象?

[英]How to rotate an object around world axis and not local axis in Opengl?

描述:在我的程序中,我確實有一個對象,單擊它時將繪制 3 個旋轉軸。 通過單擊其中一個軸並四處移動鼠標,可以旋轉對象。

問題:對象總是圍繞本地而不是世界軸旋轉,這會導致不良行為。 為了解決這個問題,我嘗試了這個,但是它也不起作用。

代碼:當我加載對象時,我旋轉它使其面向相機。

    m_phantomRotationMatrix = glm::rotate(m_phantomRotationMatrix, -90 * glm::pi<float>() / 180.0f, glm::vec3(1.0f, 0.0f, 0.0f));
    m_phantomRotationMatrix = glm::rotate(m_phantomRotationMatrix, 90 * glm::pi<float>() / 180.0f, glm::vec3(0.0f, 0.0f, 1.0f));

然后在鼠標移動的事件處理程序中,如果鼠標移動,我將執行進一步的旋轉

        case 5: // X rotation axis
        {
            GLfloat xCurrentPosition = wxGetMousePosition().x;
            GLfloat yCurrentPosition = wxGetMousePosition().y;

            m_phantomRotationMatrix = glm::rotate(m_phantomRotationMatrix, (xCurrentPosition - m_xLastPosition) * glm::pi<float>() / 180.0f, glm::vec3(1.0f, 0.0f, 0.0f));

            m_xLastPosition = xCurrentPosition;
            m_yLastPosition = yCurrentPosition;
            break;
        }
        case 6: // Y rotation axis
        {
            GLfloat xCurrentPosition = wxGetMousePosition().x;
            GLfloat yCurrentPosition = wxGetMousePosition().y;

            m_phantomRotationMatrix = glm::rotate(m_phantomRotationMatrix, (yCurrentPosition - m_yLastPosition) * glm::pi<float>() / 180.0f, glm::vec3(0.0f, 1.0f, 0.0f));

            m_xLastPosition = xCurrentPosition;
            m_yLastPosition = yCurrentPosition;
            break;
        }
        case 7: // Z rotation axis
        {
            GLfloat xCurrentPosition = wxGetMousePosition().x;
            GLfloat yCurrentPosition = wxGetMousePosition().y;

            m_phantomRotationMatrix = glm::rotate(m_phantomRotationMatrix, (xCurrentPosition - m_xLastPosition) * glm::pi<float>() / 180.0f, glm::vec3(0.0f, 0.0f, 1.0f));

            m_xLastPosition = xCurrentPosition;
            m_yLastPosition = yCurrentPosition;
            break;
        }

主循環

void MyGLCanvas::draw(wxDC& dc)
{
    wxGLCanvas::SetCurrent(*m_glContext);
    glEnable(GL_MULTISAMPLE);
    glViewport(0, 0, m_windowWidth, m_windowHeight);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_STENCIL_TEST);
    glClearDepth(1.0f);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glDepthFunc(GL_LEQUAL);

    m_rotationAngleAroundPhantom++;
    glm::mat4 phantomModel, view, projection;
    phantomModel = glm::translate(phantomModel, m_phantomPosition);
    view = m_fpsCamera->getViewMatrix();
    projection = m_fpsCamera->getProjectionMatrix(m_windowWidth, m_windowHeight);
    m_color = glm::vec4(0.310f, 0.747f, 0.185f, 1.0f);
    glm::vec3 lightPos = glm::vec3(0.0f, 1.0f, 0.0f);
    glm::vec3 lightColor = glm::vec3(1.0f, 1.0f, 1.0f);

    ShaderProgram shaderProgram;
    shaderProgram.loadShaders("Shaders/phantom.vert", "Shaders/phantom.frag");

    glClearStencil(0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    shaderProgram.use();
    shaderProgram.setUniform("phantomRotationMatrix", m_phantomRotationMatrix);
    shaderProgram.setUniform("model", phantomModel);
    shaderProgram.setUniform("view", view);
    shaderProgram.setUniform("projection", projection);
    shaderProgram.setUniform("color", m_color);
    shaderProgram.setUniform("lightColor", lightColor);
    shaderProgram.setUniform("lightPos", m_fpsCamera->getPosition());
    shaderProgram.setUniform("cameraPos", m_fpsCamera->getPosition());

    glStencilMask(0xFF); // Write to stencil buffer
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    glStencilFunc(GL_ALWAYS, 0, 0xFF);  // Set any stencil to 0

    glStencilFunc(GL_ALWAYS, 1, 0xFF); // Set any stencil to object ID
    m_pantomMesh->draw();
    glStencilFunc(GL_ALWAYS, 0, 0xFF);  // Set any stencil to 0
    shaderProgram.deleteProgram();

    if (phantomIsSelected && leftMouseClicked)
    {
        drawMovementAxes(phantomModel, view, projection);
    }

    if (phantomIsSelected && rightMouseClicked)
    {
        drawRotationAxes(phantomModel, view, projection);
    }

    glFlush();
    wxGLCanvas::SwapBuffers();
}

頂點着色器

#version 330 core

layout (location = 0) in vec3 pos;
layout (location = 1) in vec3 normal;
out vec4 vert_color;
out vec3 Normal;
out vec3 FragPos;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 phantomRotationMatrix;
uniform vec4 color;

void main()
{
    vert_color = color;
    gl_Position = projection * view * model * phantomRotationMatrix * vec4(pos.x, pos.y, pos.z, 1.0);
    FragPos = vec3(model * phantomRotationMatrix * vec4(pos, 1.0));
    Normal = vec3(transpose(inverse(phantomRotationMatrix)) * vec4(normal, 0.0));
}

你有你的模型視圖矩陣(實際上,它在你的着色器中),但你可以在你的 CPU 中完全相同地計算它。 您只需要將旋轉矩陣的反轉與模型矩陣相乘即可​​獲得對象空間中的旋轉,然后將其乘以/應用到您的對象。

如果我正確理解您的代碼,您或多或少會這樣做:

   World = View * Model * RotationMatrix * Object

然后, RotationMatrix應用於對象。 如果我了解您的需求,您希望:

   World = View * WorldRotationMatrix * Model * Object

然后你只需要求解矩陣方程,使得Model * RotationMatrix2 = WorldRotationMatrix * Model

因此,如果A * B = T ,則A-1*A * B = A-1*T => B = A-1 * T

RotationMatrix2 = Model-1 * WorldRotationMatrix * Model

在我上面的符號中, -1代表矩陣的求逆。

請看這里

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM