Я кодировал очень простую систему частиц в специальном приложении, и теперь я пытаюсь повторно использовать код в игре, которую разрабатываю.
Частицы представлены структурой, какследует:
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)