vao管理多网格模型

时间:2014-07-07 08:05:53

标签: c++ pointers 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 = &(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 = &(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 = &(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, &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, &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, &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, &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 个答案:

答案 0 :(得分:0)

您正在为本地变量分配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 - 它应该只使用一次;在每次迭代中,你都会丢失以前的数据。

目前还不清楚如何在不再需要它们时删除顶点数组,因为调用方不知道这些值是什么。

相关问题