2016-12-04 6 views
1

Несколько дней назад я задаю вопрос о том, как использовать edge collapse with Assimp. Гладкий OBJ и удалить дубликаты вершин программного обеспечения sloved основной проблемы, которая может сделать край коллапс работы, я имею в виду его работу, потому что это может быть simplicated по MeshLab так: simplified meshУпрощение сетки с Assimp и OpenMesh

Он хорошо выглядит в MeshLab, но я тогда сделайте это в моем двигателе, который использовал Assimp и OpenMesh. Проблема заключается в . Ассимпер импортировал указанные вершины и индексы, которые могли позволить полуприцепу пропустить противоположную пару. (Это называется не многообразием?). В результате снимка использовать OpenMesh в квадрике прореживание:

Decimation by OpenMesh

Чтобы очистить, чтобы найти проблему, я делаю это без прореживания и анализировать структуру OpenMesh данных обратно непосредственно. Все работает нормально, как и ожидалось (я имею в виду результат без прореживания).

Without Decimation

Код, который я использовал проредить сетку:

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; 
} 

также обеспечивают the tree obj я протестирована и the face data, что сгенерированный Assimp, я извлечь из Visual Studio отладчик, который показывает проблема в том, что некоторые индексы не смогли найти пара индексов.

+0

Вы подтвердили, что это не потому, что вы не рисуете «спину» лиц? То естьнормали пропавших лиц указывают внутри дерева. –

ответ

0

Несколько недель думая об этом и терпят неудачу, я думал, что я хочу некоторые Academic/математического решения для автоматического создания этой прореженной сетки, но теперь я пытаюсь найти простого способ осуществить это, как я я могу изменить структуру загрузки multi-object (file.obj) в отдельный пользовательский объект (класс obj) и переключать объект, когда это необходимо. В пользу этого я могу управлять тем, что должно присутствовать и игнорировать любую проблему с алгоритмом.

Кстати, я перечисляю некоторые препятствия, которые подталкивают меня к простому пути.

  1. Уникальные индексы и вершины Ассимпа, это не что иное, но для алгоритма невозможно создать для этого структуру полукрестности смежности.
  2. OpenMesh для чтения только объектного файла (*. Obj), это можно сделать при использовании функции read_mesh, но недостатком является отсутствие примера документа и сложность в использовании в моем движке.
  3. Написать заказ импортера 3d модели для любого формата сложно.

В заключение, есть два способа повысить уровень детализации работы в двигателе, один использует алгоритм упрощения сетки и больше тестов для обеспечения качества, другой - просто переключить 3dмодель, сделанный программным обеспечением 3d, It не является автоматическим, но стабильным. Я использую второй метод, и я покажу результат здесь :)

this work!

Однако, это не является реальным решением с моим вопросом, поэтому я не буду приписывать мне ответ.