如何访问碰撞模型数据?

Posted

技术标签:

【中文标题】如何访问碰撞模型数据?【英文标题】:How to access assimp model data for collisions? 【发布时间】:2018-02-14 04:20:52 【问题描述】:

这似乎是一项简单的任务,但我似乎无法弄清楚如何使用从 assimp 导入的数据来测试三角形碰撞。我已经确定我的三角形碰撞算法工作正常,并且将顶点和索引缓冲到 openGL EBO 和 VBO 中以完美地进行绘图。我被认为是我从 std::vector 的顶点和索引访问数据的方式不正确。目前我使用索引作为顶点向量的索引。

 void loadModel(std::string path) 
        Assimp::Importer importer;
        const aiScene * scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_JoinIdenticalVertices);
        if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) 
            printf_s("Assimp loading error \n%s\n", importer.GetErrorString());
            return;
        
        directory = path.substr(0, path.find_last_of('/'));
        processNode(scene->mRootNode, scene);
    
    void processNode(aiNode * node, const aiScene * scene) 
        for (unsigned int i = 0; i < node->mNumMeshes; i++) 
            //processes all the nodes meshes
            aiMesh * mesh = scene->mMeshes[node->mMeshes[i]];
            meshes.push_back(processMesh(mesh, scene));
        
        for (unsigned int i = 0; i < node->mNumChildren; i++) 
            processNode(node->mChildren[i], scene);
        
    
    Mesh processMesh(aiMesh * mesh, const aiScene * scene) 
        std::vector<Vertex> vertices;
        std::vector<unsigned int> indices;
        std::vector<Texture> textures;
        for (unsigned int i = 0; i < mesh->mNumVertices; i++)  
            Vertex vertex;
            glm::vec3 vector;
            vector.x = mesh->mVertices[i].x;
            vector.y = mesh->mVertices[i].y;
            vector.z = mesh->mVertices[i].z;
            vertex.position = vector;
            //get other vertex information
            vertices.push_back(vertex);
            //for all vertices in the mesh, adds the data to a vector
        
        for (unsigned int i = 0; i < mesh->mNumFaces; i++) 
            aiFace face = mesh->mFaces[i];
            if (face.mNumIndices == 3) 
                indices.push_back(face.mIndices[0]);                    
                indices.push_back(face.mIndices[1]);
                indices.push_back(face.mIndices[2]);
                //for all the indices in each face, add each indice

            
            else 
                printf("Odd mNumIndices \n");
                //added as a just in case - but in my situation this case is never executed -> all faces are triangles
                for (unsigned int j = 0; j < face.mNumIndices; j++) 
                    indices.push_back(face.mIndices[j]);
                
            
        

现在要访问这些数据,我只需遍历模型的所有网格,并为网格的每个索引访问其对应的顶点。

bool collision(glm::mat4 worldSpaceTransform, glm::vec3 testVector) 
        for (Mesh mesh : meshes) 
            for (int i = 0; i < mesh.indices.size(); i += 3) 
                //iterate through all faces of the mesh since each face has 3 vertices
                glm::vec3 a = glm::vec3(worldSpaceTransform * glm::vec4(mesh.verticies[mesh.indices[i]].position, 1));
                glm::vec3 b = glm::vec3(worldSpaceTransform * glm::vec4(mesh.verticies[mesh.indices[i + 1]].position, 1));
                glm::vec3 c = glm::vec3(worldSpaceTransform * glm::vec4(mesh.verticies[mesh.indices[i + 2]].position, 1)); 
               //use vector a, b and c (transformed to world space) for collision test with the test vector
               //return true if the test vector collides with the triangle
            
        
        return false;
    

所以我使用 print 语句来输出向量 a b 和 c 的坐标,这应该构成一个三角形。在一种情况下,我在模型的原始 .obj 文件中找不到这些精确的向量,我找到了它们的 x、y 和 z 坐标,但不是全部都在一个向量中(是的,当我检查这个时,我打印了局部空间坐标)。在另一个例子中,应该构成三角形的三个向量最终形成一条线(三个向量中的两个具有相同的坐标)。此外,我知道使用模型的所有原语测试向量效率低下,但现在我专注于让 something 工作,然后再查看优化。许多模型对于 AABB 来说太复杂了,所以这是我想出的“最佳”解决方案。所以,我不确定我在这里做错了什么,非常感谢任何提示!

【问题讨论】:

您是否检查过使用的最大索引是否等于 vertices.size?只是为了检查没有子网格。 @Jay 是的,没有子网格。还有比顶点更多的索引,这当然是意料之中的,但是即使我没有使用 aiProcess_JoinIdenticalVertices,这也不是预期的 3 比 1 的比例 【参考方案1】:

obj 格式只存储每个顶点一次,并将在面中引用它。所以 Assimp 将从这些位置生成渲染本身的顶点。这就是您无法从导入的 obj 文件中以 obj 格式存储它们的原始信息的原因。 Obj 针对大小进行了优化,assimp 使用的中间格式针对渲染进行了优化。

存储碰撞信息的好策略很大程度上取决于您的模型类型。对我来说,它可以为整个模型生成局部边界框,并为存储在节点图中的每个网格生成子框。所以以下方法可能有效:

检查场景边界框是否您的三角形与此框相撞 如果是这种情况: 检查所有节点边界框​​ 如果您能够检测到碰撞:检查网格内该节点的所有三角形以找到正确的三角形

【讨论】:

这是我最终试图解决冲突的地方,但现在我似乎无法从 assimp 访问正确的顶点数据。我现在知道我不应该在 obj 文件中寻找完全相同的顶点来检查我的数据,但我应该能够从 assimp 访问顶点数据并对模型中的每个三角形进行暴力碰撞检测测试.也许我没有完全理解?再次感谢

以上是关于如何访问碰撞模型数据?的主要内容,如果未能解决你的问题,请参考以下文章

我小时候在我的玩家类中为我的玩家制作了一个碰撞箱精灵。如何在游戏场景的 didBegin 方法中访问该碰撞箱精灵?

如何使许多类都可以访问 Arraylist?

如何访问列表中元组的第一个元素?

JVM高级特性-JVM在堆中对象的分配布局访问过程

如何让单元测试访问核心数据模型

如何从辅助函数访问模型以查询数据库?