繁体   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