управление vao для модели с несколькими сетками

#c #pointers #opengl #vbo #vao

#c #указатели #opengl #vbo #vao

Вопрос:

У меня есть модель .obj с несколькими сетками. Я хочу создать vao для каждой сетки. А затем визуализируйте все это.

Для этого я хочу создать указатель vao, изменяющий его размер в зависимости от количества ячеек в модели.

Я загружаю модель с помощью assimp.

Проблем с компиляцией нет, но при выполнении этого происходит сбой программы.

       glBindVertexArray(modele_multvao[z]);
      glDrawArrays(GL_TRIANGLES, 0, modele_multcount[z]);
  

Представление о том, что не так в моей программе? (я вроде как новичок в OpenGL)

Мой код:

 GLuint *modele_vao;
int *point_count;
int number_of_mesh;

bool load_mesh(const char* file_name, GLuint* vao, int* point_count,int* num_mesh) {
/* load file with assimp and print some stats */
const aiScene* scene = aiImportFile(file_name, aiProcess_Triangulate);
if (!scene) {
    std::wcout <<"ERROR: reading mesh: "<< file_name << std::endl;
    std::wcout << aiGetErrorString() << std::endl;
    return false;
}
std::wcout << "mesh import succeeded" << std::endl;
std::wcout << scene->mNumAnimations << " animations" << std::endl;
std::wcout << scene->mNumCameras << " cameras" << std::endl;
std::wcout << scene->mNumLights << " lights" << std::endl;
std::wcout << scene->mNumMaterials << " materials" << std::endl;
std::wcout << scene->mNumMeshes << " meshes" << std::endl;
std::wcout << scene->mNumTextures << " textures" << std::endl;

num_mesh=scene->mNumMeshes;
vao = new GLuint[scene->mNumMeshes];
point_count=new int[scene->mNumMeshes];

int i=0;
for(i=1;i<=(scene->mNumMeshes);i  )
{
    /* get mesh n°i in file  */
    const aiMesh* mesh = scene->mMeshes[i-1];
    std::wcout << "vertices in mesh :" << mesh->mNumVertices<< std::endl;

    /* pass back number of vertex points in mesh */
    *point_count = mesh->mNumVertices;

    /* generate a VAO, using the pass-by-reference parameter that we give to the
    function */

    glGenVertexArrays(scene->mNumMeshes, vao);
    glBindVertexArray(vao[i-1]);

    /* we really need to copy out all the data from AssImp's funny little data
    structures into pure contiguous arrays before we copy it into data buffers
    because assimp's texture coordinates are not really contiguous in memory.
    i allocate some dynamic memory to do this. */
    GLfloat* points = NULL; // array of vertex points
    GLfloat* normals = NULL; // array of vertex normals
    GLfloat* texcoords = NULL; // array of texture coordinates
    if (mesh->HasPositions()) {
        points = (GLfloat*)malloc(*point_count * 3 * sizeof (GLfloat));
        for (int i = 0; i < *point_count; i  ) {
            const aiVector3D* vp = amp;(mesh->mVertices[i]);
            points[i * 3] = (GLfloat)vp->x;
            points[i * 3   1] = (GLfloat)vp->y;
            points[i * 3   2] = (GLfloat)vp->z;
        }
    }
    if (mesh->HasNormals()) {
        normals = (GLfloat*)malloc(*point_count * 3 * sizeof (GLfloat));
        for (int i = 0; i < *point_count; i  ) {
            const aiVector3D* vn = amp;(mesh->mNormals[i]);
            normals[i * 3] = (GLfloat)vn->x;
            normals[i * 3   1] = (GLfloat)vn->y;
            normals[i * 3   2] = (GLfloat)vn->z;
        }
    }
    if (mesh->HasTextureCoords(0)) {
        texcoords = (GLfloat*)malloc(*point_count * 2 * sizeof (GLfloat));
        for (int i = 0; i < *point_count; i  ) {
            const aiVector3D* vt = amp;(mesh->mTextureCoords[0][i]);
            texcoords[i * 2] = (GLfloat)vt->x;
            texcoords[i * 2   1] = (GLfloat)vt->y;
        }
    }

    /* copy mesh data into VBOs */
    if (mesh->HasPositions()) {
        GLuint vbo_pos;
        glGenBuffers(1, amp;vbo_pos);
        glBindBuffer(GL_ARRAY_BUFFER, vbo_pos);
        glBufferData(
            GL_ARRAY_BUFFER,
            3 * *point_count * sizeof (GLfloat),
            points,
            GL_DYNAMIC_DRAW
            );
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, NULL);
        glEnableVertexAttribArray(0);
        free(points); // free our temporary memory
    }
    if (mesh->HasNormals()) {
        GLuint vbo_norm;
        glGenBuffers(1, amp;vbo_norm);
        glBindBuffer(GL_ARRAY_BUFFER, vbo_norm);
        glBufferData(
            GL_ARRAY_BUFFER,
            3 * *point_count * sizeof (GLfloat),
            normals,
            GL_DYNAMIC_DRAW
            );
        glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, NULL);
        glEnableVertexAttribArray(2);
        free(normals); // free our temporary memory
    }
    if (mesh->HasTextureCoords(0)) {
        GLuint vbo_tex;
        glGenBuffers(1, amp;vbo_tex);
        glBindBuffer(GL_ARRAY_BUFFER, vbo_tex);
        glBufferData(
            GL_ARRAY_BUFFER,
            2 * *point_count * sizeof (GLfloat),
            texcoords,
            GL_DYNAMIC_DRAW
            );
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
        glEnableVertexAttribArray(1);
        free(texcoords); // free our temporary memory
    }
    if (mesh->HasTangentsAndBitangents()) {
        // NB: could store/print tangents here
    }
}

/* free assimp's copy of memory */
aiReleaseImport(scene);
std::wcout << "mesh loaded" << std::endl;

return true;
}



int main()
{
    load_mesh("somewhere", modele_vao, point_count, amp;num_of_mesh)

    [...]

    while(1){

        [...]

        for(z=0;z<num_of_mesh;z  ){
            glBindVertexArray(modele_vao[z]);
            glDrawArrays(GL_TRIANGLES, 0, modele_count[z]);
        }

    }
}
  

Ответ №1:

Вы присваиваете new массивы ed локальным переменным. После возврата функции эта память теряется.

Это должно быть что-то вроде:

 bool load_mesh(const char* file_name, GLuint** _vao, int** _point_count,int* num_mesh)
  

(обратите внимание ** на два параметра и _ для примера)

И затем,:

 GLuint *vao = new GLuint[scene->mNumMeshes];
*_vao = vao;
  

И то же самое для второго параметра.

num_mesh это указатель, но вы присваиваете ему целое число (и оно локальное, поэтому значение снова теряется). Так и должно быть *num_mesh = scene->mNumMeshes; .

Другое дело, что вы используете glGenVertexArrays в цикле — его следует использовать только один раз; на каждой итерации вы теряете предыдущие данные.

Неясно, как вы собираетесь удалять свои массивы вершин, когда они вам больше не понадобятся, поскольку вызывающая сторона понятия не имеет, что это за значения.