2016-10-26 11 views
1

モデルを.obj形式でインポートすると、多くのポリゴンが頂点を共有し、無駄にメモリを消費するため、一意の頂点だけを保存して重複を削除します。すべての頂点が含まれているときに最初の画像である頂点 tinyobjcloaderモデル内の頂点の重複排除

Mesh Renderer::load_mesh_from_file(std::string filepath) { 
tinyobj::attrib_t attrib; 
std::vector<tinyobj::shape_t> shapes; 
std::vector<tinyobj::material_t> materials; 
std::string err; 
auto success = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filepath.c_str()); 
if (!success) { SDL_Log("Failed loading mesh %s: %s", filepath.c_str(), err.c_str()); return Mesh(); } 

std::unordered_map<Vertex<float>, size_t> unique_vertices{}; 
Mesh mesh{}; 
for (auto shape : shapes) { // Shapes 
    size_t index_offset = 0; 
    for (auto face : shape.mesh.num_face_vertices) { // Faces (polygon) 
     for (auto v = 0; v < face; v++) { 
      tinyobj::index_t idx = shape.mesh.indices[index_offset + v]; 
      Vertex<float> vertex{}; 
      float vx = attrib.vertices[3 * idx.vertex_index + 0]; 
      float vy = attrib.vertices[3 * idx.vertex_index + 1]; 
      float vz = attrib.vertices[3 * idx.vertex_index + 2]; 
      vertex.position = {vx, vy, vz}; 

      float tx = attrib.vertices[3 * idx.texcoord_index + 0]; 
      float ty = attrib.vertices[3 * idx.texcoord_index + 1]; 
      vertex.texCoord = {tx, ty}; 

      float nx = attrib.normals[3 * idx.normal_index + 0]; 
      float ny = attrib.normals[3 * idx.normal_index + 1]; 
      float nz = attrib.normals[3 * idx.normal_index + 2]; 
      vertex.normal = {nx, ny, nz}; 

      // These two lines work just fine (includes all vertices) 
      // mesh.vertices.push_back(vertex); 
      // mesh.indices.push_back(mesh.indices.size()); 

      // Check for unique vertices, models will contain duplicates 
      if (unique_vertices.count(vertex) == 0) { 
       unique_vertices[vertex] = mesh.indices.size(); 
       mesh.vertices.push_back(vertex); 
       mesh.indices.push_back(mesh.indices.size()); 
      } else { 
       mesh.indices.push_back(unique_vertices.at(vertex)); 
      } 
     } 
     index_offset += face; 
    } 
} 

SDL_Log("Number of vertices: %lu for model %s", mesh.vertices.size(), filepath.c_str()); 
return mesh; 
} 

でメッシュをインポート

/// Template specialization for hashing of a Vec3 
namespace std { 
template<typename T> 
struct hash<Vec3<T>> { 
    void hash_combine(size_t &seed, const size_t &hash) const { 
     seed ^= hash + 0x9e3779b9 + (seed << 6) + (seed >> 2); 
    } 

    size_t operator() (const Vec3<T> &vec) const { 
     auto hasher = hash<float>{}; 
     auto hashed_x = hasher(vertex.position.x); 
     auto hashed_y = hasher(vertex.position.y); 
     auto hashed_z = hasher(vertex.position.z); 
     auto hashed_color_r = hasher(vertex.color.r); 
     auto hashed_color_g = hasher(vertex.color.g); 
     auto hashed_color_b = hasher(vertex.color.b); 
     auto hashed_color_a = hasher(vertex.color.a); 
     auto hashed_texcoord_x = hasher(vertex.texCoord.x); 
     auto hashed_texcoord_y = hasher(vertex.texCoord.y); 
     auto hashed_normal_x = hasher(vertex.normal.x); 
     auto hashed_normal_y = hasher(vertex.normal.y); 
     auto hashed_normal_z = hasher(vertex.normal.z); 

     size_t seed = 0; 
     hash_combine(seed, hashed_x); 
     hash_combine(seed, hashed_y); 
     hash_combine(seed, hashed_z); 
     hash_combine(seed, hashed_texcoord_x); 
     hash_combine(seed, hashed_texcoord_y); 
     hash_combine(seed, hashed_normal_x); 
     hash_combine(seed, hashed_normal_y); 
     hash_combine(seed, hashed_normal_z); 
     return seed; 
    } 
}; 
} 

ハッシュ。

enter image description here

私は唯一のユニークな頂点を使用していたときにこの1つはあります。

enter image description here

任意のアイデア?

答えて

1

(unique_vertices.count(頂点)== 0)[頂点] = {メッシュ

unique_vertices場合。 頂点 .size();

mesh.indices.push_back(メッシュ。頂点 .size());

mesh.vertices.push_back(頂点);

説明:インデックスは、頂点の位置に対する「ポインタ」です。そのためには、頂点データを書き出すインデックスを取得し、インデックスデータのインデックスは取得しないでください。

+0

うん!今回もこのことが問題でした!インデックスが常に順番(0,1,2、...、n)だったので、チェックなしでうまくいったのは不思議ではありません。 – Entalpi

1

表示された画像から、これは三角形頂点参照問題のようです。

通常、obj formatは、固有の頂点のリストを収集し、各三角形は、3つの頂点に対応する3つのインデックスのセットです。なんらかの理由で、頂点Aと頂点Bを繰り返し、頂点Bを削除することにしたとしましょう。この場合、Bを含むすべての三角形の参照を修正し、それらをAに置き換える必要があります。

+0

Hmm ..仕様では頂点が一意である必要があると言われるものは何も見つかりません。 :/ – Entalpi

+0

彼らはそうではありませんが、賢明なメッシュ作成者は繰り返しを入れません(繰り返しがある場合、冗長性は必要以上のスペースを占有します)。しかし、これは、たとえばメッシュが繰り返しのあるSTLファイルから変換された場合に発生します。 – Nic

+0

@Entalpiメッシュが同じ頂点xyzを持つが、異なるtexCoordを持つ可能性はありますか?いくつかのテクスチャは、異なるテクスチャ座標で同じ座標を繰り返す必要がある頂点でジャンプする座標を持つことがあります。しかし、それはまれであり、レンダリングの違いを説明するべきではありません。私が見ることができるコーディング・エラーは、u座標からコピー・ペーストされているテクスチャーv座標を読み取ったときだけです。 –

0

繰り返し座標を削除するのは良い考えではありません。座標は、例えば、メッシュ間のステッチ領域で繰り返され、閉じた3Dメッシュ構造を形成する。 3Dゲームでは、低レンダリングが可能な低ポリゴンメッシュ構造が採用されていますが、特にそうでない限り、これらのポイントクラウドを扱うことは大きな問題ではありません。現在のところ、強力なGPUやマルチコアCPUシステムにより、

関連する問題