Не удается обновить содержимое VBO с помощью memcpy - PullRequest
0 голосов
/ 10 ноября 2019

Я кодировал очень простую систему частиц в специальном приложении, и теперь я пытаюсь повторно использовать код в игре, которую разрабатываю.

Частицы представлены структурой, какследует:

struct Particle
{
    glm::vec3 position;
    float lifeTime;
    glm::vec3 direction;

    Particle(glm::vec3 pos, glm::vec3 dir)
    {
        position = pos;
        lifeTime = 0.0f;
        direction = dir;
    }
};

И они хранятся в векторе, который содержится в качестве атрибута в классе Smoke. Класс Smoke получил свои собственные VAO и VBO и свой метод draw.

Когда я вызываю Smoke :: draw (...), я связываю VAO, рисую частицы, а затем обновляю векторное содержимое с помощью некоторого новогоЧастицы добавляются к нему, чтобы в конечном итоге пытаться обновить VBO! Вот где весь процесс завершается ошибкой.

Вот код ошибки:

    // fill VBO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    void* ptr = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
    std::cout << "ptr = " << ptr << std::endl;
    std::cout << "alloc size = " << particles.size() * sizeof(Particle) << std::endl;
    int bufferSize = 0;
    glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bufferSize);
    std::cout << "buffer size = " << bufferSize << std::endl;
    memcpy(ptr, particles.data(), particles.size() * sizeof(Particle));
    glUnmapBuffer(GL_ARRAY_BUFFER);

    // unbind VAO
    glBindVertexArray(0);

Я получаю либо ошибку сегментации, либо неправильный размер порции malloc. Кроме того, std :: cout показал мне, что ptr не равен NULL, и на этом этапе в векторе было только 6 частиц. В конструкторе Smoke я инициализировал VBO размером MAX_PARTICLES * sizeof (Particle), а вектор содержит 3 исходные частицы. MAX_PARTICLES - это #define со значением 240.

Есть идеи, почему memcpy дает сбой?

Edit => Вот весь код для метода Smoke :: draw

void Smoke::draw(double delta, glm::mat4 model_matrix, glm::mat4 view_matrix, Animation* anim, int frame, Shader* smoke_shader, Object* podracer)
{
    std::vector<Keyframe*>& keys = anim->get_keyframes();
    int kFrame_count = keys.size();
    int k = frame;
    while(k < kFrame_count && keys.at(k)->get_frame() != k)
    {
        k++;
    }
    Keyframe* kFrame = keys.at(k);
    std::vector<JointPose*>& jPoseList = kFrame->get_joint_pose_list();
    int nbJointPose = jPoseList.size();

    glm::mat4 pose[80];
    glm::mat4 tr[80];
    for(int i = 0; i < 80; i++)
    {
        pose[i] = glm::mat4(1.0f);
        tr[i] = glm::mat4(1.0f);
    }

    for(int b = 0; b < nbJointPose; b++)
    {
        std::string jPoseName = jPoseList.at(b)->name;
        Joint* currentJoint = podracer->joints_ptr_list[jPoseName];

        int jointID = currentJoint->get_id();
        glm::mat4 poseMatrix = jPoseList.at(b)->poseMatrix;
        glm::mat4 transform = currentJoint->get_transform();

        pose[jointID - 1] = poseMatrix;
        tr[jointID - 1] = transform;
    }

    // send joints pose to an array in the smoke vertex shader
    for(int m = 0; m < 80; m++)
    {
        std::string arg1("transform[");
        arg1 += std::to_string(m);
        arg1 += "]";

        std::string arg2("bones[");
        arg2 += std::to_string(m);
        arg2 += "]";

        smoke_shader->set_Matrix(arg1, tr[m]);
        smoke_shader->set_Matrix(arg2, pose[m]);
    }

    Joint* skeleton = podracer->get_skeleton();
    glm::mat4 inv_tr = skeleton->get_inverse_transform();
    smoke_shader->set_Matrix("inv_transform", inv_tr);

    // draw particles
    glBindVertexArray(VAO);
    glDrawArrays(GL_POINTS, 0, particles.size());

    // update particles VBO
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> dis(0.0, jitter);
    int particles_count = particles.size();
    auto it = particles.begin();

    for(int i = 0; i < particles.size(); i++)
    {
        Particle p = particles.at(i);
        float updated_lifeTime = p.lifeTime + static_cast<float>(delta);
        if(updated_lifeTime >= dissolve)
        {
            particles.erase(it + i);
        }
        else
        {
            p.lifeTime = updated_lifeTime;
            p.position += velocity * p.direction;// particle direction
            float jitter_x = dis(gen);
            float jitter_y = dis(gen);
            float jitter_z = dis(gen);
            p.position += glm::vec3(jitter_x * p.direction.x, jitter_y * p.direction.y, jitter_z * p.direction.z);
        }
    }

    int bID = static_cast<int>(boneID);
    glm::mat4 animMatrix = inv_tr * pose[bID - 1] * tr[bID - 1];

    glm::vec4 pos_s1 = model_matrix * animMatrix * glm::vec4(s1, 1.0f);
    glm::vec4 pos_s2 = model_matrix * animMatrix * glm::vec4(s2, 1.0f);
    glm::vec4 pos_s3 = model_matrix * animMatrix * glm::vec4(s3, 1.0f);
    glm::vec4 new_dir = model_matrix * animMatrix * glm::vec4(direction, 1.0f);

    particles.insert(it, Particle(glm::vec3(pos_s1), glm::vec3(new_dir)));
    particles.insert(it, Particle(glm::vec3(pos_s2), glm::vec3(new_dir)));
    particles.insert(it, Particle(glm::vec3(pos_s3), glm::vec3(new_dir)));

    // fill VBO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    void* ptr = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);

    std::cout << "ptr = " << ptr << std::endl;
    std::cout << "alloc size = " << particles.size() * sizeof(Particle) << std::endl;
    int bufferSize = 0;
    glGetBufferParameteriv(GL_ARRAY_BUFFER, GL_BUFFER_SIZE, &bufferSize);
    std::cout << "buffer size = " << bufferSize << std::endl;

    memcpy(ptr, particles.data(), particles.size() * sizeof(Particle));
    glUnmapBuffer(GL_ARRAY_BUFFER);

    // unbind VAO
    glBindVertexArray(0);
}

Некоторые сообщения из GDB:

radeon: The kernel rejected CS, see dmesg for more information (-2).
ptr = 0x7fffe20ff000
alloc size = 168
buffer size = 6720
#8  0x00000000004439f6 in std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_construct<char*> (this=0x7fffffff6230, 
    __beg=0x4d605000000000 <error: Cannot access memory at address 0x4d605000000000>, __end=0x324d807000000000 <error: Cannot access memory at address 0x324d807000000000>)
    at /usr/include/c++/9/bits/basic_string.tcc:219
#9  0x0000000000470e2d in Smoke::draw (this=0x6d2940, delta=0.022781162999308435, model_matrix=..., view_matrix=..., anim=0x49a8210, frame=0, smoke_shader=0x49ed8a0, podracer=0x7752b0)
...