簡體   English   中英

如何在 openGL 中圍繞全局軸旋轉 model?

[英]How to rotate a model around a global axis in openGL?

在 OpenGL 中,我想圍繞全局軸旋轉 Model。

我試圖旋轉的 object 看起來像這樣:

class Object {
public:
    inline Object()
        : vao(0),
        positionBuffer(0),
        colorBuffer(0),
        indexBuffer(0),
        elements(0)
    {}

    inline ~Object() { // GL context must exist on destruction
        glDeleteVertexArrays(1, &vao);
        glDeleteBuffers(1, &indexBuffer);
        glDeleteBuffers(1, &colorBuffer);
        glDeleteBuffers(1, &positionBuffer);
    }
    GLuint vao;        // vertex-array-object ID
    GLuint positionBuffer; // ID of vertex-buffer: position
    GLuint colorBuffer;    // ID of vertex-buffer: color
    GLuint indexBuffer;    // ID of index-buffer
    GLuint elements; // Number of Elements
    glm::mat4x4 model; // model matrix
};

啟動 object 的 function 看起來像:

void initObject(Object &obj, vector<glm::vec3> &vertices, vector<glm::vec3> &colors, vector<GLushort> &indices, glm::vec3 offset)
{
    GLuint programId = program.getHandle();
    GLuint pos;

    glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);

    // Step 0: Create vertex array object.
    glGenVertexArrays(1, &obj.vao);
    glBindVertexArray(obj.vao);

    // Step 1: Create vertex buffer object for position attribute and bind it to the associated "shader attribute".
    glGenBuffers(1, &obj.positionBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, obj.positionBuffer);
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), vertices.data(), GL_STATIC_DRAW);

    // Bind it to position.
    pos = glGetAttribLocation(programId, "position");
    glEnableVertexAttribArray(pos);
    glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 0, 0);

    // Step 2: Create vertex buffer object for color attribute and bind it to...
    glGenBuffers(1, &obj.colorBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, obj.colorBuffer);
    glBufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(glm::vec3), colors.data(), GL_STATIC_DRAW);

    // Bind it to color.
    pos = glGetAttribLocation(programId, "color");
    glEnableVertexAttribArray(pos);
    glVertexAttribPointer(pos, 3, GL_FLOAT, GL_FALSE, 0, 0);

    // Step 3: Create vertex buffer object for indices. No binding needed here.
    glGenBuffers(1, &obj.indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, obj.indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(GLushort), indices.data(), GL_STATIC_DRAW);

    // Unbind vertex array object (back to default).
    glBindVertexArray(0);

    // Modify model matrix.
    obj.model = glm::translate(glm::mat4(1.0f), offset);
}

現在我得到了一個實例,它是作為球體的鑲嵌八面體,我想圍繞全局軸旋轉,特別是 X 軸。 Object 的中心位於 (3, 1, 0) 處,因此如果原點位於 (3, 0, 1) 處,則圍繞 90 度旋轉。

我嘗試使用glm::rotate方法來做到這一點:

glm::vec3 axis;
axis = { 1.0, 0.0f, 0.0f };
sphere.model = glm::rotate(sphere.model, glm::radians(90.0f), axis);

但這只會圍繞其本地軸旋轉 object。

我嘗試的另一個解決方案是這個:

glm::vec3 axis;
axis = glm::inverse(sphere.model) * glm::vec4(1.0, 0.0, 0.0, 0.0f);
sphere.model = glm::rotate(sphere.model, (2.0f*3.1415f)/48.0f, axis);

另一方面,就像全局軸位於 model 的中心一樣。 因此,如果 object 的中心等於全局坐標系的原點,則旋轉是正確的。

我會向@genpfault 致敬。 聽起來 glm::rotate 的實現是這樣一個: https://github.com/g-truc/glm/blob/1498e094b95d1d89164c6442c632d775a2a1bab5/glm/ext/matrix_transform.inl

因此它不涉及平移,它只改變矩陣的旋轉部分,就像設置東西一樣。 為了執行動畫或組合不同的轉換,您需要使用另一個 API。

retMat = glm::rotate(curMat, ...)計算旋轉矩陣並將其與給定的curMat矩陣相乘。

返回的矩陣retMat可以與在與curMat相同的坐標系(又稱“空間”)中定義的任何點一起使用,以計算新坐標,再次在相同的空間中: newXYZ = retMat * oldXYZ

glm::rotate的旋轉軸總是穿過空間的原點。
如果您需要另一條旋轉線(不包含原點),那么您必須執行“平移到線上的某個點 ==> 旋轉 ==> 向后平移”的順序

對於你的情況,我猜你的球體是這樣定義的,它的中心是原點0,0,0 這意味着“模型空間”與“全局空間”相同。 因此,您無需在旋轉之前平移球體。


旋轉 object 后,將其平移到您希望的位置。

在您的模型+視圖+投影 (MVP) 矩陣(或四元數)操作中,您正在混合 model 和視圖矩陣。 您需要將 model 從單位矩陣旋轉到所需的 RPY 矩陣。 然后,您將 object 移動和/或旋轉到您想要在 XYZ 空間中的位置。 最后,您可以根據需要應用正交投影或透視投影。

關鍵是您應該分別跟蹤 OBJECT 的原點相對於 GLOBAL 原點的位置。 換句話說,您擁有 object 的質心所在的位置,還有旋轉中心(不一定是全局原點)。

為了在 object 質心的局部框架中旋轉 object,您需要首先擺脫平移組件。 這是模型+視圖部分。 您可以通過對 4x4 矩陣的最后一列中的 XYZ 元素進行逆矩陣來做到這一點。 然后將 4x4 旋轉矩陣應用於質心。 然后將 object 移回所需的質心位置。

這有意義嗎?

我建議您更多地研究 MVP model。 OGL 4 着色語言食譜(由 Packt 提供)是一個很好的資源。 還有這個鏈接這個

但是,我應該注意,您應該熟悉 glm 矩陣庫的后端。 我使用了一個自定義矩陣庫,顯示了rotate() function 的實現。

暫無
暫無

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

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