0

この方法でデータを保存する obj ファイルがあります。

v value1 value2 value3  
f value1 value2 value3

最初に面の法線を計算し、次にその面の各頂点に割り当てます。

for(int i = 0; i < verticesInd.size(); i+=3)
{
    glm::vec3 normal = glm::normalize(glm::cross(glm::vec3(vertices[verticesInd[i + 1]]) - glm::vec3(vertices[verticesInd[i]]), glm::vec3(vertices[verticesInd[i + 2]]) - glm::vec3(vertices[verticesInd[i]])));
    out_Normals[i] = normal;
    out_Normals[i + 1] = normal;
    out_Normals[i + 2] = normal;
}

フラット シェーディングを実現するために、頂点を複製できます。

for(int i = 0; i < verticesInd.size(); i++)
{
    out_Vertices.push_back(vertices[verticesInd[i]]);
} 

次に、glDrawArrays を使用してオブジェクトを描画します。

glDrawArrays(GL_TRIANGLES, 0, out_Vertices.size());

滑らかなシェーディングを実現するには、各頂点の法線を平均化する必要がありますが、隣接する面を見つける方法がわかりません。

Edit1: f: の前に単一の s パラメータに気づきませんでした:

v value1 value2 value3
s 1  
f value1 value2 value3

Edit2:法線の平均化

glm::vec3 tNormal;
for(int i = 0; i < vertices.size(); i++)
{
    for(int  j = 0; j < verticesInd.size(); j++)
    {
        if(verticesInd[j] == i)
        {
            tNormal += faceNormals[j / 3];
        }
    }
    aNormals.push_back(glm::normalize(tNormal));
    tNormal = glm::vec3(0,0,0);
}

3 つの面の法線を編集します。

for(int i = 0; i < verticesInd.size(); i+=3)
{
    glm::vec3 normal = glm::normalize(glm::cross(glm::vec3(vertices[verticesInd[i + 1]]) - glm::vec3(vertices[verticesInd[i]]), glm::vec3(vertices[verticesInd[i + 2]]) - glm::vec3(vertices[verticesInd[i]])));
    faceNormals.push_back(normal);
}
4

3 に答える 3

1

ほとんどのオブジェクト形式では、隣接する面は頂点を共有する必要があります。頂点で滑らかなシェーディングされた法線を見つけることは、その頂点を使用する面の法線を平均化することです。

既存の頂点配列と同じサイズの追加の新しい配列を作成することをお勧めします。

各面を反復処理し、頂点インデックスごとに、その頂点の面法線を新しい配列に追加します。

プロセスの最後に、結果の法線ベクトルを正規化し、以前に計算された顔の法線の代わりにそれを使用します。

あなたのデータ構造を正しく理解していれば、次のようになります。

glm::vec3 aNormals[];   // one for each vertex - use the appropriate constructor

for (int i = 0; i < verticesInd.size(); ++i) {
    int f = i / 3;                 // which face is this index part of (3 per face?)
    int v = verticesInd[i];        // which vertex number is being used
    aNormals[v] += faceNormals[f]; // add the face normal to this vertex
}

// now normalise aNormals
于 2012-08-27T17:12:10.007 に答える
0

フラグメント ライティングごとにこの男https://www.youtube.com/watch?v=MRD_zN0SWh0&feature=plcpに従ってください。私の知る限り、頂点ごとに法線を見つけるための同じ方程式が含まれています。

顔のリストが必要です。波面オブジェクトを見たことがあるなら。これらには、複数の三角形インデックス 4,7,2 1,2,3 が含まれています。顔を表す 3 つの数字。通常のメッシュでは、各ポイントは 3 回しか使用できません。3 を持つ各グループを見つけると、それぞれの顔を見つけることができます。対応する正常値を見つけてから平均します。

Alnitak にも有効な情報があります。頂点のリストがあり、それらを 3 つのグループとしてリストして、頂点を面データとして再利用 (共有) できるようにします。

于 2012-08-27T16:03:21.383 に答える
0

隣接する面を見つける方法がわかりません。

OBJ ローダー内の一時的な頂点ストレージに面のリストを追加します。フェース ラインを処理しているときに、参照する各頂点のフェース リストに新しいフェースを追加します。

こうすることで、最後にすべての頂点をスピンし、それが属していた面を調べ、面の法線を取得して平均化することができます。

あなたの OBJ がそのような優れた組み込みの接続性情報を持っていない場合 (そして、そうしなければならないという要件はありません)、近くにある頂点 (および対応する面) を見つけるために、各頂点で最近傍検索を行う必要があります。それ。お気に入りの空間インデックスを使用して、これらの種類のクエリを高速化します。

于 2012-08-27T17:04:15.417 に答える