简体   繁体   English

OpenGL形状仅在初始位置为(0,0,0)时绘制

[英]OpenGL shape only draws when initial position is (0, 0, 0)

I have a cube that I am loading from an OBJ file. 我有一个要从OBJ文件加载的多维数据集。 When I make its position (0, 0, 0) everything works fine. 当我将其位置设置为(0,0,0)时,一切正常。 The cube renders, and my function that gives it a velocity moves the cube across the screen. 立方体渲染,我的函数给它一个速度,使立方体在屏幕上移动。 However if I change the position of the cube to something other than (0, 0, 0) before entering my while loop where I render and calculate velocity changes, the cube never renders. 但是,如果在进入渲染和计算速度变化的while循环之前,将立方体的位置更改为(0,0,0)以外的其他位置,则立方体将永远不会渲染。 This is the first time I have tried to reload my vertices every time I render a frame, and I am assuming I messed up something there - but I've looked over other code and can't figure out what. 这是我第一次在每次渲染框架时都尝试重新加载顶点,并且我假设我在那里弄乱了一些东西,但是我查看了其他代码,无法弄清楚是什么。

Here is my main function: 这是我的主要功能:

int main()
{
#ifdef TESTING
    testing();
    exit(0);
#endif

    setupAndInitializeWindow(768, 480, "Final Project");

    TriangleTriangleCollision collisionDetector;

    Asset cube1("cube.obj", "vertexShader.txt", "fragmentShader.txt");

    cube1.position = glm::vec3(0.0, 2.0, 0.0);
    cube1.velocity = glm::vec3(0.0, -0.004, 0.0);

    MVP = projection * view * model;

    do{
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        moveAsset(cube1);

        renderAsset(cube1);

        glfwSwapBuffers(window);
        glfwPollEvents();

    } while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
        glfwWindowShouldClose(window) == 0);

    glfwTerminate();

    return 0;
}

my moveAsset function: 我的moveAsset函数:

void moveAsset(Asset &asset)
{
    double currentTime = glfwGetTime();

    asset.position.x += (asset.velocity.x * (currentTime - asset.lastTime));
    asset.position.y += (asset.velocity.y * (currentTime - asset.lastTime));
    asset.position.z += (asset.velocity.z * (currentTime - asset.lastTime));

    for (glm::vec3 &vertex : asset.vertices)
    {
        glm::vec4 transformedVector = glm::translate(glm::mat4(1.0f), asset.position) * glm::vec4(vertex.x, vertex.y, vertex.z, 1);
        vertex = glm::vec3(transformedVector.x, transformedVector.y, transformedVector.z);
    }

    asset.lastTime = glfwGetTime();
}

void renderAsset(Asset asset)
{   
    glUseProgram(asset.programID);

    GLuint MatrixID = glGetUniformLocation(asset.programID, "MVP");
    glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);

    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, asset.vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, asset.vertices.size() * sizeof(glm::vec3), &asset.vertices[0], GL_STATIC_DRAW);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
    glDrawArrays(GL_TRIANGLES, 0, asset.vertices.size());

    glDisableVertexAttribArray(0);
}

my model, view and projection matrices are defined as: 我的模型,视图和投影矩阵定义为:

glm::mat4 model = glm::mat4(1.0f);
glm::mat4 view = glm::lookAt(glm::vec3(5, 5, 10),
                            glm::vec3(0, 0, 0),
                            glm::vec3(0, 1, 0));
glm::mat4 projection = glm::perspective(45.0f, (float) _windowWidth / _windowHeight, 0.1f, 100.0f);

and finally, my Asset struct: 最后,我的资产结构:

struct Asset
{
    Asset() { }
    Asset(std::string assetOBJFile, std::string vertexShader, std::string fragmentShader)
    {
        glGenVertexArrays(1, &vertexArrayID);
        glBindVertexArray(vertexArrayID);

        programID = LoadShaders(vertexShader.c_str(), fragmentShader.c_str());

        // Read our .obj file
        std::vector<glm::vec2> uvs;
        std::vector<glm::vec3> normals;
        loadOBJ(assetOBJFile.c_str(), vertices, uvs, normals);

        // Load it into a VBO
        glGenBuffers(1, &vertexbuffer);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(glm::vec3), &vertices[0], GL_STATIC_DRAW);

        //velocity = glm::vec3(0.0, 1.0, 1.0);
        velocity = glm::vec3(0.0, 0.0, 0.0);
        position = glm::vec3(0.0, 0.0, 0.0);

        lastTime = glfwGetTime();
    }

    GLuint vertexArrayID;
    GLuint programID;

    GLuint vertexbuffer;

    std::vector<glm::vec3> faces;
    std::vector<glm::vec3> vertices;

    glm::vec3 velocity;

    double lastTime;
    glm::vec3 position;
};

It looks like you're adding the current asset.position to your vertex positions on every iteration , replacing the previous positions. 好像您是在每次迭代中将当前asset.position添加到顶点位置,以替换先前的位置。 From the moveAsset() function: moveAsset()函数中:

for (glm::vec3 &vertex : asset.vertices)
{
    glm::vec4 transformedVector = glm::translate(glm::mat4(1.0f), asset.position) *
                                  glm::vec4(vertex.x, vertex.y, vertex.z, 1);
    vertex = glm::vec3(transformedVector.x, transformedVector.y, transformedVector.z);
}

Neglecting the velocity for a moment, and assuming that you have an original vertex at (0, 0, 0), you would move it to asset.position on the first iteration. 暂时忽略速度,并假设您在(0,0,0)处有一个原始顶点,则可以在第一次迭代时将其移动到asset.position Then add asset.position again on the second iteration, which places it at 2 * asset.position . 然后在第二次迭代中再次添加asset.position ,将其放置在2 * asset.position Then on the third iteration, add asset.position to this current position again, resulting in 3 * asset.position . 然后在第三次迭代中,再次将asset.position添加到该当前位置,得到3 * asset.position So after n steps, the vertices will be around n * asset.position . 因此,在n步之后,顶点将围绕n * asset.position Even if your object might be visible initially, it would move out of the visible range before you can blink. 即使您的对象最初可能是可见的,在眨眼之前它也会移出可见范围。

To get your original strategy working, the most straightforward approach is to have two lists of vertices. 为了使您的原始策略生效,最直接的方法是拥有两个顶点列表。 One list contains your original object coordinates, which you never change. 一个列表包含您原始的对象坐标,您永远不会更改。 Then before you draw, you build a second list of vertices, calculated as the sum of the original vertices plus the current asset.position , and use that second list for rendering. 然后,在绘制之前,您将构建第二个顶点列表,将其计算为原始顶点加上当前asset.position ,然后使用该第二个列表进行渲染。

The whole thing is... not very OpenGL. 整个问题是...不是非常OpenGL。 There's really no need to modify the vertex coordinates on the CPU. 确实不需要修改CPU上的顶点坐标。 You can make the translation part of the transformation applied in your vertex shader. 您可以将转换的一部分应用到顶点着色器中。 You already have a model matrix in place. 您已经有一个模型矩阵。 You can simply put the translation by asset.position into the model matrix, and recalculate the MVP matrix. 您可以简单地asset.position进行的平移放入模型矩阵,然后重新计算MVP矩阵。 You already have the glUniformMatix4fv() call to pass the new matrix to the shader program in your renderAsset() function. 您已经具有glUniformMatix4fv()调用,以将新矩阵传递给renderAsset()函数中的着色器程序。

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

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