首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >更新网格VBO

更新网格VBO
EN

Stack Overflow用户
提问于 2020-05-12 18:30:24
回答 1查看 161关注 0票数 0

我用弹丸物理引擎运行了一个软体模拟,因此我必须更新每个框架的网格顶点的位置。为此,我使用以下函数:

代码语言:javascript
复制
void Mesh::update_VBO(std::vector<Vertex> const & updated_vertices)
{
    indices.clear();
    for(int i = 0; i < updated_vertices.size(); i++)
    {
        indices.push_back(i);
    }

    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

    void * VBO_ptr = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
    void * EBO_ptr = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
    memcpy(VBO_ptr, updated_vertices.data(), updated_vertices.size() * sizeof(Vertex));
    memcpy(EBO_ptr, indices.data(), indices.size() * sizeof(int));

    glUnmapBuffer(GL_ARRAY_BUFFER);
    glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);

    vertices.clear();
    vertices = updated_vertices;
}

现在,问题是,有时我有一个分割错误,有时它运行时没有错误。我确信这个问题来自于这个函数,因为当我用下面的代码替换上面的代码时,突然之间,没有错误,一切都运行良好(我所调用的重新创建函数的唯一缺点是,它导致了一些非常糟糕的性能,因为我删除了以前的VAO,创建了一组新的VAO VBO和EBO):

代码语言:javascript
复制
void Mesh::update_VBO(std::vector<Vertex> const & updated_vertices)
{
    indices.clear();
    for(int i = 0; i < updated_vertices.size(); i++)
    {
        indices.push_back(i);
    }
    recreate(updated_vertices, indices);
/*
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);

    void * VBO_ptr = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
    void * EBO_ptr = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
    memcpy(VBO_ptr, updated_vertices.data(), updated_vertices.size() * sizeof(Vertex));
    memcpy(EBO_ptr, indices.data(), indices.size() * sizeof(int));

    glUnmapBuffer(GL_ARRAY_BUFFER);
    glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);

    vertices.clear();
    vertices = updated_vertices;
*/
}

还有一件事是,update_VBO函数是我为一个简单的程序做的函数,它有两个立方体通过绳子连接在一起,整个东西都掉在地上了,对于这个小程序来说,一切都很好。

但是现在我将这个函数合并到我的主要项目中,它失败了。

我遗漏了什么?

编辑:这是修复我的问题的代码,如下面的注释部分所述。

代码语言:javascript
复制
// recreate cable left mesh
        prev_c_left_vertices = init_previous_vertices(vertices, fixed_left_vertices);
        g->pod->cable_left->get_mesh_collection().at(0)->recreate(prev_c_left_vertices, fixed_left_indices);
代码语言:javascript
复制
// recreate cable right mesh
        prev_c_right_vertices = init_previous_vertices(vertices, fixed_right_vertices);
        g->pod->cable_right->get_mesh_collection().at(0)->recreate(prev_c_right_vertices, fixed_right_indices);

这是我创建软身体的完整代码:

代码语言:javascript
复制
    // ----------********** CABLES CREATION
    // step simulation
    dynamicsWorld->stepSimulation(1.0f/60.0f, 10);

    // chariot model
    btTransform transform_chariot;
    if(chariot_body && chariot_body->getMotionState())
        chariot_body->getMotionState()->getWorldTransform(transform_chariot);
    transform_chariot.getOpenGLMatrix(glm::value_ptr(chariot_model));

    // -----***** create cable left soft body
    Mesh* cable_left_mesh = g->pod->cable_left->get_mesh_collection().at(0);
    // get rid of duplicated vertices
    std::vector<Vertex> vertices = cable_left_mesh->get_vertex_list();
        for(int i = 0; i < vertices.size(); i++)
        {
            glm::vec3 before = vertices.at(i).position;
            glm::vec4 before2(before.x, before.y, before.z, 1.0f);
            glm::vec4 after = chariot_model * glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -0.02f, 0.3f)) * before2;
            vertices.at(i).position = glm::vec3(after.x, after.y, after.z);
        }
        std::vector<int> indices = cable_left_mesh->get_index_list();

        std::vector<Vertex> fixed_left_vertices;
        std::vector<int> fixed_left_indices;

        std::vector<std::pair<glm::vec3, int>> couple;

        for(int i = 0; i < indices.size(); i += 3) // for each face
        {
            // get the 3 couples of the current face
            glm::vec3 a_pos = vertices.at(indices.at(i)).position;
            int a_index = indices.at(i);

            glm::vec3 b_pos = vertices.at(indices.at(i+1)).position;
            int b_index = indices.at(i+1);

            glm::vec3 c_pos = vertices.at(indices.at(i+2)).position;
            int c_index = indices.at(i+2);

            // check for each couple if its position is already defined by another couple in the clean array
            int a_def_index = get_vertex_defined_index(a_pos, a_index, couple);
            int b_def_index = get_vertex_defined_index(b_pos, b_index, couple);
            int c_def_index = get_vertex_defined_index(c_pos, c_index, couple);

            if(a_def_index == -1)
                couple.push_back(std::make_pair(a_pos, a_index));
            if(b_def_index == -1)
                couple.push_back(std::make_pair(b_pos, b_index));
            if(c_def_index == -1)
                couple.push_back(std::make_pair(c_pos, c_index));
        }

        for(int i = 0; i < couple.size(); i++)
        {
            int couple_index = couple.at(i).second;
            fixed_left_vertices.push_back(vertices.at(couple_index));
        }

        for(int i = 0; i < indices.size(); i += 3)
        {
            glm::vec3 a_pos = vertices.at(indices.at(i)).position;
            glm::vec3 b_pos = vertices.at(indices.at(i+1)).position;
            glm::vec3 c_pos = vertices.at(indices.at(i+2)).position;

            fixed_left_indices.push_back(retrieve_correct_index(a_pos, couple));
            fixed_left_indices.push_back(retrieve_correct_index(b_pos, couple));
            fixed_left_indices.push_back(retrieve_correct_index(c_pos, couple));
        }

        // create left soft body
        cable_left = btSoftBodyHelpers::CreateFromTriMesh(*softBody_worldInfo, vertex_list_2_btScalarArray(fixed_left_vertices), fixed_left_indices.data(), fixed_left_indices.size() / 3);

        // create left soft body material
        btSoftBody::Material* left_material = cable_left->appendMaterial();
        left_material->m_kLST = 0.75f;
        left_material->m_kAST = 0.0f;
        left_material->m_kVST = 1.0f;

        cable_left->generateBendingConstraints(5, left_material);
        cable_left->generateClusters(32);
        cable_left->setPose(true, false);
        cable_left->setTotalMass(0.65f, true);
        cable_left->m_cfg.piterations = 10;
        cable_left->randomizeConstraints();

        // add left soft body to the dynamics world
        dynamicsWorld->addSoftBody(cable_left);
        initial_c_left_vertices = fixed_left_vertices;
        prev_c_left_vertices = fixed_left_vertices;

        // attach left soft body to chariot and reactors
        btSoftBody::tNodeArray left_nodes = cable_left->m_nodes;

        std::qsort(fixed_left_vertices.data(), fixed_left_vertices.size(), sizeof(Vertex), cmp_vertex);

        for(int i = 0; i < left_nodes.size(); i++)
        {
            btVector3 pos = left_nodes.at(i).m_x;
            for(int j = 0; j < 21; j++)
            {
                glm::vec3 v_pos = fixed_left_vertices.at(j).position;
                if(pos.x() == v_pos.x && pos.y() == v_pos.y && pos.z() && v_pos.z)
                {
                    cable_left->appendAnchor(i, chariot_body);
                }
            }
        }

        for(int i = 0; i < left_nodes.size(); i++)
        {
            btVector3 pos = left_nodes.at(i).m_x;
            for(int j = fixed_left_vertices.size() - 1; j > fixed_left_vertices.size() - 22; j--)
            {
                glm::vec3 v_pos = fixed_left_vertices.at(j).position;
                if(pos.x() == v_pos.x && pos.y() == v_pos.y && pos.z() && v_pos.z)
                {
                    cable_left->appendAnchor(i, reactors_body);
                }
            }
        }

        // recreate cable left mesh
        prev_c_left_vertices = init_previous_vertices(vertices, fixed_left_vertices);
        g->pod->cable_left->get_mesh_collection().at(0)->recreate(prev_c_left_vertices, fixed_left_indices);

        // -----***** create cable right soft body
        Mesh* cable_right_mesh = g->pod->cable_right->get_mesh_collection().at(0);
        // get rid of duplicated vertices
        vertices.clear(); indices.clear();
        vertices = cable_right_mesh->get_vertex_list();
        for(int i = 0; i < vertices.size(); i++)
        {
            glm::vec3 before = vertices.at(i).position;
            glm::vec4 before2(before.x, before.y, before.z, 1.0f);
            glm::vec4 after = chariot_model * glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, -0.02f, 0.3f)) * before2;
            vertices.at(i).position = glm::vec3(after.x, after.y, after.z);
        }
        indices = cable_right_mesh->get_index_list();

        std::vector<Vertex> fixed_right_vertices;
        std::vector<int> fixed_right_indices;

        couple.clear();

        for(int i = 0; i < indices.size(); i += 3) // for each face
        {
            // get the 3 couples of the current face
            glm::vec3 a_pos = vertices.at(indices.at(i)).position;
            int a_index = indices.at(i);

            glm::vec3 b_pos = vertices.at(indices.at(i+1)).position;
            int b_index = indices.at(i+1);

            glm::vec3 c_pos = vertices.at(indices.at(i+2)).position;
            int c_index = indices.at(i+2);

            // check for each couple if its position is already defined by another couple in the clean array
            int a_def_index = get_vertex_defined_index(a_pos, a_index, couple);
            int b_def_index = get_vertex_defined_index(b_pos, b_index, couple);
            int c_def_index = get_vertex_defined_index(c_pos, c_index, couple);

            if(a_def_index == -1)
                couple.push_back(std::make_pair(a_pos, a_index));
            if(b_def_index == -1)
                couple.push_back(std::make_pair(b_pos, b_index));
            if(c_def_index == -1)
                couple.push_back(std::make_pair(c_pos, c_index));
        }

        for(int i = 0; i < couple.size(); i++)
        {
            int couple_index = couple.at(i).second;
            fixed_right_vertices.push_back(vertices.at(couple_index));
        }

        for(int i = 0; i < indices.size(); i += 3)
        {
            glm::vec3 a_pos = vertices.at(indices.at(i)).position;
            glm::vec3 b_pos = vertices.at(indices.at(i+1)).position;
            glm::vec3 c_pos = vertices.at(indices.at(i+2)).position;

            fixed_right_indices.push_back(retrieve_correct_index(a_pos, couple));
            fixed_right_indices.push_back(retrieve_correct_index(b_pos, couple));
            fixed_right_indices.push_back(retrieve_correct_index(c_pos, couple));
        }

        // create right soft body
        cable_right = btSoftBodyHelpers::CreateFromTriMesh(*softBody_worldInfo, vertex_list_2_btScalarArray(fixed_right_vertices), fixed_right_indices.data(), fixed_right_indices.size() / 3);

        // create right soft body material
        btSoftBody::Material* right_material = cable_right->appendMaterial();
        right_material->m_kLST = 0.75f;
        right_material->m_kAST = 0.0f;
        right_material->m_kVST = 1.0f;

        cable_right->generateBendingConstraints(5, right_material); // 2
        cable_right->generateClusters(32);
        cable_right->setPose(true, false);
        cable_right->setTotalMass(0.65f, true);
        cable_right->m_cfg.piterations = 10;
        cable_right->randomizeConstraints();

        // add right soft body to the dynamics world
        dynamicsWorld->addSoftBody(cable_right);
        initial_c_right_vertices = fixed_right_vertices;
        prev_c_right_vertices = fixed_right_vertices;

        // attach right soft body to chariot and reactors
        btSoftBody::tNodeArray right_nodes = cable_right->m_nodes;

        std::qsort(fixed_right_vertices.data(), fixed_right_vertices.size(), sizeof(Vertex), cmp_vertex);

        for(int i = 0; i < right_nodes.size(); i++)
        {
            btVector3 pos = right_nodes.at(i).m_x;
            for(int j = 0; j < 21; j++)
            {
                glm::vec3 v_pos = fixed_right_vertices.at(j).position;
                if(pos.x() == v_pos.x && pos.y() == v_pos.y && pos.z() && v_pos.z)
                {
                    cable_right->appendAnchor(i, chariot_body);
                }
            }
        }

        for(int i = 0; i < right_nodes.size(); i++)
        {
            btVector3 pos = right_nodes.at(i).m_x;
            for(int j = fixed_right_vertices.size() - 1; j > fixed_right_vertices.size() - 22; j--)
            {
                glm::vec3 v_pos = fixed_right_vertices.at(j).position;
                if(pos.x() == v_pos.x && pos.y() == v_pos.y && pos.z() && v_pos.z)
                {
                    cable_right->appendAnchor(i, reactors_body);
                }
            }
        }

        // recreate cable right mesh
        prev_c_right_vertices = init_previous_vertices(vertices, fixed_right_vertices);
        g->pod->cable_right->get_mesh_collection().at(0)->recreate(prev_c_right_vertices, fixed_right_indices);
EN

回答 1

Stack Overflow用户

发布于 2020-05-12 18:33:54

听起来,您似乎在尝试在缓冲区中推送比为其分配空间更多的顶点。只有在缓冲区大小相同的情况下,才能随意更新缓冲区,如果您想要增加顶点的数量,就必须重新分配缓冲区。

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

https://stackoverflow.com/questions/61759353

复制
相关文章

相似问题

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