首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在openGL中围绕全局轴旋转模型?

如何在openGL中围绕全局轴旋转模型?
EN

Stack Overflow用户
提问于 2020-06-04 23:53:27
回答 3查看 663关注 0票数 0

在OpenGL中,我希望围绕全局轴旋转模型。

我试图旋转的对象看起来像这样:

代码语言:javascript
复制
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
};

初始化对象的函数如下所示:

代码语言:javascript
复制
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轴。该对象的中心位于(3,1,0),因此绕90度旋转的原点应位于(3,0,1)。

我尝试使用glm::rotate方法完成此操作:

代码语言:javascript
复制
glm::vec3 axis;
axis = { 1.0, 0.0f, 0.0f };
sphere.model = glm::rotate(sphere.model, glm::radians(90.0f), axis);

但这只会使对象围绕其局部轴旋转。

我尝试的另一个解决方案是这个:

代码语言:javascript
复制
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);

这是另一种行为,就像全局轴在模型的中心。因此,如果对象的中心等于全局坐标系的原点,则旋转是正确的。

EN

回答 3

Stack Overflow用户

发布于 2020-06-05 01:23:31

我会把Kudos归于@genpfault。听起来像是glm::rotate的实现是一个:https://github.com/g-truc/glm/blob/1498e094b95d1d89164c6442c632d775a2a1bab5/glm/ext/matrix_transform.inl

因此,它不涉及平移,它只改变矩阵的旋转部分,就像设置东西一样。为了执行动画或组合不同的转换,您需要使用另一个API。

票数 0
EN

Stack Overflow用户

发布于 2020-06-05 02:19:32

retMat = glm::rotate(curMat, ...)计算旋转矩阵,并将其与给定的curMat矩阵相乘。

返回的矩阵retMat可以与在与curMat相同的坐标系(也称为“空间”)中定义的任何点一起使用,以计算新的坐标,同样是在相同的空间中:newXYZ = retMat * oldXYZ

指定给glm::rotate的旋转轴始终经过空间的原点。

如果您需要另一条旋转线(不包含原点),则必须执行序列"translate to some on line ==> rotate ==> translate back"

对于你的例子,我猜你的球体是这样定义的,它的中心是原点0,0,0。这意味着“模型空间”与“全局空间”是相同的。因此,您不需要在旋转之前平移球体。

一旦您旋转了对象,然后将其平移到您想要的点。

票数 0
EN

Stack Overflow用户

发布于 2020-06-07 00:11:03

在model+view+projection (MVP)矩阵(或四元数)操作中,您混合了模型矩阵和视图矩阵。您需要将模型从单位矩阵旋转到所需的RPY矩阵。然后,将对象移动和/或旋转到XYZ空间中所需的位置。最后,根据需要应用正交投影或透视投影。

重点是,您应该分别跟踪对象的原点相对于全局原点的位置。换句话说,您不仅拥有希望对象的质心所在的位置,还拥有旋转的中心(不一定是全局原点)。

为了在对象质心的局部框架中旋转对象,首先需要去除平移组件。这是Model+View部分。您可以通过在4x4矩阵的最后一列中仅对XYZ元素进行逆矩阵来实现这一点。然后将4x4旋转矩阵应用于质心。然后将对象移回所需的质心位置。

这有意义吗?

我建议你更多地研究MVP模型。OGL 4着色语言食谱(由Packt编写)是一个很好的资源。还有this linkthis one

但是,我应该注意到,您应该熟悉glm矩阵库的后端。我使用了一个自定义矩阵库,它展示了rotate()函数的实现。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62198942

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档