OpenGL 围绕自身而不是原点 (0,0,0) 旋转一个对象(一组立方体)

OpenGL Rotating an object (set of cubes) around itself rather than the origin (0,0,0)

我正在练习 OpenGL 和变换,运行 遇到了问题。我有四个立方体平移在一起形成汽车的骨架。我希望能够在汽车不自行拆卸的情况下驾驶和转动汽车。基本上,我希望 t运行k 和汽车的前部围绕汽车的车身而不是原点 (0,0,0) 旋转。我读过要完成此操作,我必须遵循以下步骤:

  1. 从单位矩阵开始

  2. 通过对象的中心平移矩阵

  3. 将矩阵旋转所需的量

  4. 以物体为中心平移矩阵

  5. 使用生成的矩阵来变换您想要旋转的对象

并已将其实现到我的代码中,但它没有像我预期的那样工作。请告诉我我做错了什么以及实现它的正确方法。我在下面粘贴了我的代码,并对其进行了修剪,因此这里只显示重要部分。

结果:

float xMove = 0.0f;  //xMove and zMove keeps track of the center of the main body while driving
float zMove = 0.0f;
float carRotate = 0.0f;  //degrees of rotation incremented by pressing E

int main()
{
/*some code to initialize the program...*/

    while (!glfwWindowShouldClose(window))
    {
    /*Draw main car body*/

        mat4 carMatrix = translate(mat4(1.0f), vec3(0.0f + xMove + x, 0.2f, 0.0f + zMove + z))
            * rotate(mat4(1.0f), radians(carRotate), vec3(0.0f, 1.0f, 0.0f))
            * scale(mat4(1.0f), vec3(0.5f, 0.4f, 1.0f))
            * translate(mat4(1.0f), vec3(0.0f, -0.2f,0.0f));
        shaderProgram.setMat4("model", carMatrix);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        //Bonnet
        carMatrix = translate(mat4(1.0f), vec3(0.0f + xMove + x, 0.1f, 0.65f + zMove + z))
            * rotate(mat4(1.0f), radians(carRotate), vec3(0.0f, 1.0f, 0.0f))
            * scale(mat4(1.0f), vec3(0.3f, 0.2f, 0.3f))
            * translate(mat4(1.0f), vec3(xMove, 0.0f, -zMove));
        shaderProgram.setMat4("model", carMatrix);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        //Trunk
        carMatrix = translate(mat4(1.0f), vec3(0.0f + xMove + x, 0.1f, -0.65f + zMove + z))
            * rotate(mat4(1.0f), radians(carRotate), vec3(0.0f, 1.0f, 0.0f))
            * scale(mat4(1.0f), vec3(0.3f, 0.2f, 0.3f))
            * translate(mat4(1.0f), vec3(0.0f, 0.0f, 0.0f));
        shaderProgram.setMat4("model", carMatrix);
        glDrawArrays(GL_TRIANGLES, 0, 36);

        //Roof
        carMatrix = translate(mat4(1.0f), vec3(0.0f + xMove + x, 0.45f, 0.0f + zMove + z))
            * rotate(mat4(1.0f), radians(carRotate), vec3(0.0f, 1.0f, 0.0f))
            * scale(mat4(1.0f), vec3(0.3f, 0.1f, 0.6f))
            * translate(mat4(1.0f), vec3(0.0f, 0.0f, 0.0f));
        shaderProgram.setMat4("model", carMatrix);
        glDrawArrays(GL_TRIANGLES, 0, 36);


    if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
    {
        zMove++;
    }
    if (glfwGetKey(window, GLFW_KEY_E) == GLFW_PRESS)
    {
        carRotate++;
    }
}
}

不要"Translate the matrix by -centre of the object".

然后把整辆车放在那个地方,它的中心在(0, 0, 0)。 Thant 表示将每个对象平移到其相对于 (0, 0, 0) 的位置。然后缩放和旋转。最后把关心移到世界上的位置。

如果小车的一部分相对于(0,0,0)的位置为(relX,relY,relZ),则:

mat4 carMatrix = 
    translate(mat4(1.0f), vec3(xMove + x, 0.0f, zMove + z) * 
    rotate(mat4(1.0f), radians(carRotate), vec3(0.0f, 1.0f, 0.0f));

//Bonnet
mat4 partMatrix_1 = 
    translate(mat4(1.0f), vec3(relX, relY, relZ)) * 
    scale(mat4(1.0f), vec3(0.5f, 0.4f, 1.0f));

shaderProgram.setMat4("model", carMatrix * partMatrix_1);
glDrawArrays(GL_TRIANGLES, 0, 36);

//Trunk
mat4 partMatrix_2 = 
    translate(mat4(1.0f), vec3(relX2, relY2, relZ2)) * 
    scale(mat4(1.0f), vec3(0.3f, 0.2f, 0.3f));

shaderProgram.setMat4("model", carMatrix * partMatrix_2);
glDrawArrays(GL_TRIANGLES, 0, 36);

// [...]

注意,我建议先缩放每个部分。然后放回原处。

relXrelYrelZ 是汽车每个部件的常数和独立坐标。