简体   繁体   English

如何在 openGL 中围绕全局轴旋转 model?

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

In OpenGL i want to rotate a Model around a global Axis.在 OpenGL 中,我想围绕全局轴旋转 Model。

The object I am trying to rotate looks like this:我试图旋转的 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
};

The function to initiate an object looks like:启动 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);
}

Now I got an instance of that which is tessellated octahedron acting as a sphere, which i want to rotate around a global Axis, specifically the X axis.现在我得到了一个实例,它是作为球体的镶嵌八面体,我想围绕全局轴旋转,特别是 X 轴。 The center of that Object is at (3, 1, 0) so that a rotation around 90 degrees should the origin be at (3, 0, 1). Object 的中心位于 (3, 1, 0) 处,因此如果原点位于 (3, 0, 1) 处,则围绕 90 度旋转。

I tried to do this with the glm::rotate Method:我尝试使用glm::rotate方法来做到这一点:

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

But that only rotates the object around it's local Axis.但这只会围绕其本地轴旋转 object。

Another solution I tried was this one:我尝试的另一个解决方案是这个:

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);

This one the other hand act's like the global axis is in the center of the model.另一方面,就像全局轴位于 model 的中心一样。 So the rotation would be right if the center of the object would be equal to the origin of the global coordinate system.因此,如果 object 的中心等于全局坐标系的原点,则旋转是正确的。

I would give Kudos to @genpfault.我会向@genpfault 致敬。 It sounds like the implementation of glm::rotate is that one: https://github.com/g-truc/glm/blob/1498e094b95d1d89164c6442c632d775a2a1bab5/glm/ext/matrix_transform.inl听起来 glm::rotate 的实现是这样一个: https://github.com/g-truc/glm/blob/1498e094b95d1d89164c6442c632d775a2a1bab5/glm/ext/matrix_transform.inl

Hence it doesn't touch the translation, it changes only the rotation part of the matrix, like to set the things up.因此它不涉及平移,它只改变矩阵的旋转部分,就像设置东西一样。 In order to perform animations or combine different transformation you need to use another API.为了执行动画或组合不同的转换,您需要使用另一个 API。

retMat = glm::rotate(curMat, ...) calculates the rotation matrix and multiply it with the given curMat matrix. retMat = glm::rotate(curMat, ...)计算旋转矩阵并将其与给定的curMat矩阵相乘。

The returned matrix retMat can be used with any point that was defined in the same coordinates-system (aka "space") as curMat to calculate the new coordinates, again in the same space: newXYZ = retMat * oldXYZ .返回的矩阵retMat可以与在与curMat相同的坐标系(又称“空间”)中定义的任何点一起使用,以计算新坐标,再次在相同的空间中: newXYZ = retMat * oldXYZ

The axis of rotation given to glm::rotate always goes through the origin of the space. glm::rotate的旋转轴总是穿过空间的原点。
If you need another line of rotation (not containing the origin) then you must do the sequence "translate to some point on line ==> rotate ==> translate back"如果您需要另一条旋转线(不包含原点),那么您必须执行“平移到线上的某个点 ==> 旋转 ==> 向后平移”的顺序

For your case, I guess your sphere is defined such way its center is the origin 0,0,0 .对于你的情况,我猜你的球体是这样定义的,它的中心是原点0,0,0 This means that "model space" is the same as "global space".这意味着“模型空间”与“全局空间”相同。 So, you don't need to translate the sphere before the rotation.因此,您无需在旋转之前平移球体。


Once you have rotated the object then translate it to the point you wish.旋转 object 后,将其平移到您希望的位置。

In your model+view+projection (MVP) matrix (or quaternion) operations, you are mixing your model and view matrices.在您的模型+视图+投影 (MVP) 矩阵(或四元数)操作中,您正在混合 model 和视图矩阵。 You need to rotate the model from the identity matrix to the desired RPY matrix.您需要将 model 从单位矩阵旋转到所需的 RPY 矩阵。 Then, you move and/or rotate the object to the location you want in XYZ space.然后,您将 object 移动和/或旋转到您想要在 XYZ 空间中的位置。 Finally, you apply your orthogonal projection or your perspective projection, whichever you want.最后,您可以根据需要应用正交投影或透视投影。

The point is that you should keep track of where the origin of the OBJECT is relative to the GLOBAL origin separately.关键是您应该分别跟踪 OBJECT 的原点相对于 GLOBAL 原点的位置。 In other words, you have where you want the centroid of the object to be, but also the centers of rotations (which aren't necessarily the global origin).换句话说,您拥有 object 的质心所在的位置,还有旋转中心(不一定是全局原点)。

In order to rotate an object in the object centroid's local frame, you need to first get rid of the translation component.为了在 object 质心的局部框架中旋转 object,您需要首先摆脱平移组件。 This is the Model+View part.这是模型+视图部分。 You can do this by doing the inverse matrix of just he XYZ elements in the last column of the 4x4 matrix.您可以通过对 4x4 矩阵的最后一列中的 XYZ 元素进行逆矩阵来做到这一点。 You then apply your 4x4 rotation matrix to the centroid.然后将 4x4 旋转矩阵应用于质心。 You then move the object back to the desired centroid location.然后将 object 移回所需的质心位置。

Does this make sense?这有意义吗?

I suggest you study more into the MVP model more.我建议您更多地研究 MVP model。 The OGL 4 shading language cookbook (by Packt) is a great resource. OGL 4 着色语言食谱(由 Packt 提供)是一个很好的资源。 There is also this link and this one .还有这个链接这个

I should note, however, that you should be familiar with the backend of the glm matrix library.但是,我应该注意,您应该熟悉 glm 矩阵库的后端。 I have use a custom matrix library that showed the implementation of the rotate() function.我使用了一个自定义矩阵库,显示了rotate() function 的实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM