2

数日前、 Assimp でエッジ コラプスを使用する方法について質問します。オブジェクトを滑らかにし、ソフトウェアで重複した頂点を削除すると、エッジの崩壊が機能する可能性がある基本的な問題が解決されます。つまり、MeshLab によって次のように単純化できるため、機能します。 単純化されたメッシュ

MeshLab では良さそうですが、Assimp と OpenMesh を使用したエンジンで実行します。問題は、Assimp が指定された頂点とインデックスをインポートしたことです。これにより、ハーフエッジが反対のペアを見逃す可能性があります(これは非多様体と呼ばれますか?)。結果のスナップショットは、OpenMesh の Quadric Decimation を使用します。

OpenMeshによるデシメーション

問題を解決するために、デシメーションなしで実行し、OpenMesh データ構造を直接解析します。すべてが期待どおりに正常に動作します (デシメーションなしの結果を意味します)。

間引きなし

メッシュをデシメートするために使用したコード:

Loader::BasicData Loader::TestEdgeCollapse(float vertices[], int vertexLength, int indices[], int indexLength, float texCoords[], int texCoordLength, float normals[], int normalLength)
{
    // Mesh type
    typedef OpenMesh::TriMesh_ArrayKernelT<>   OPMesh;
    // Decimater type
    typedef OpenMesh::Decimater::DecimaterT< OPMesh > OPDecimater;
    // Decimation Module Handle type
    typedef OpenMesh::Decimater::ModQuadricT< OPMesh >::Handle HModQuadric;

    OPMesh mesh;
    std::vector<OPMesh::VertexHandle> vhandles;
    int iteration = 0;
    for (int i = 0; i < vertexLength; i += 3)
    {
        vhandles.push_back(mesh.add_vertex(OpenMesh::Vec3f(vertices[i], vertices[i + 1], vertices[i + 2])));
        if (texCoords != nullptr)
            mesh.set_texcoord2D(vhandles.back(),OpenMesh::Vec2f(texCoords[iteration * 2], texCoords[iteration * 2 + 1]));
        if (normals != nullptr)
            mesh.set_normal(vhandles.back(), OpenMesh::Vec3f(normals[i], normals[i + 1], normals[i + 2]));
        iteration++;
    }

    for (int i = 0; i < indexLength; i += 3)
        mesh.add_face(vhandles[indices[i]], vhandles[indices[i + 1]], vhandles[indices[i + 2]]);

    OPDecimater decimater(mesh);
    HModQuadric hModQuadric;
    decimater.add(hModQuadric);
    decimater.module(hModQuadric).unset_max_err();
    decimater.initialize();
    //decimater.decimate(); // without this, everything is fine as expect.
    mesh.garbage_collection();

    int verticesSize = mesh.n_vertices() * 3;
    float* newVertices = new float[verticesSize];
    int indicesSize = mesh.n_faces() * 3;
    int* newIndices = new int[indicesSize];
    float* newTexCoords = nullptr;
    int texCoordSize = mesh.n_vertices() * 2;
    if(mesh.has_vertex_texcoords2D())
        newTexCoords = new float[texCoordSize];
    float* newNormals = nullptr;
    int normalSize = mesh.n_vertices() * 3;
    if(mesh.has_vertex_normals())
        newNormals = new float[normalSize];

    Loader::BasicData data;

    int index = 0;
    for (v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it)
    {
        OpenMesh::Vec3f &point = mesh.point(*v_it);
        newVertices[index * 3] = point[0];
        newVertices[index * 3 + 1] = point[1];
        newVertices[index * 3 + 2] = point[2];
        if (mesh.has_vertex_texcoords2D())
        {
            auto &tex = mesh.texcoord2D(*v_it);
            newTexCoords[index * 2] = tex[0];
            newTexCoords[index * 2 + 1] = tex[1];
        }
        if (mesh.has_vertex_normals())
        {
            auto &normal = mesh.normal(*v_it);
            newNormals[index * 3] = normal[0];
            newNormals[index * 3 + 1] = normal[1];
            newNormals[index * 3 + 2] = normal[2];
        }
        index++;
    }
    index = 0;

    for (f_it = mesh.faces_begin(); f_it != mesh.faces_end(); ++f_it)
        for (fv_it = mesh.fv_ccwiter(*f_it); fv_it.is_valid(); ++fv_it)
        {
            int id = fv_it->idx();
            newIndices[index] = id;
            index++;
        }

    data.Indices = newIndices;
    data.IndicesLength = indicesSize;
    data.Vertices = newVertices;
    data.VerticesLength = verticesSize;
    data.TexCoords = nullptr;
    data.TexCoordLength = -1;
    data.Normals = nullptr;
    data.NormalLength = -1;
    if (mesh.has_vertex_texcoords2D())
    {
        data.TexCoords = newTexCoords;
        data.TexCoordLength = texCoordSize;
    }
    if (mesh.has_vertex_normals())
    {
        data.Normals = newNormals;
        data.NormalLength = normalSize;
    }
    return data;
}

また、私がテストしたツリー objと、Assimp によって生成された面データを提供します。ビジュアル スタジオ デバッガーから取り出したもので、一部のインデックスがインデックス ペアを見つけることができなかったという問題を示しています。

4

1 に答える 1

1

これについて数週間考えて失敗しました。これらの間引きされたメッシュを自動的に生成するための学術的/数学的なソリューションが必要だと思っていましたが、今はこれを実装する簡単な方法を見つけようとしています。私ができる方法は構造を変更することです複数のオブジェクト (file.obj) を単一のカスタム オブジェクト (クラス obj)にロードし、必要に応じてオブジェクトを切り替えます。これの利点は、提示すべきものを管理し、アルゴリズムの問​​題を無視できることです。

ところで、単純な方法に戻るのを後押しするいくつかの障害をリストします。

  1. Assimp Unique Indices and Vertices、これは何も悪いことではありませんが、アルゴリズムの場合、隣接関係をハーフエッジ構造にする方法はありません。
  2. オブジェクトファイル(*.obj)のみを読み込むOpenMesh、これはread_mesh関数を使えばできますが、欠点はドキュメントの例がなく、私のエンジンでは使いにくいことです。
  3. 任意の形式のカスタム 3d モデル インポーターを作成するのは困難です。

結論として、エンジンで詳細レベルを機能させる方法は 2 つあります。1 つはメッシュ単純化アルゴリズムを使用し、品質を保証するためにさらにテストを行う方法です。もう 1 つは、3D ソフトウェアで作成した 3D モデルを切り替えるだけで、自動ではなく安定しています。私は2番目の方法を使用し、結果をここに示します:)

この作品!

ただし、これは私の質問に対する実際の解決策ではないため、回答を割り当てません。

于 2016-12-06T06:53:53.397 に答える