0

3D 65.000 の位置座標を持つ 3D の閉じたメッシュ オブジェクトがあります。ライティングの目的で、3D サーフェス法線抽出器が必要です。

手に入れるのを手伝ってくれませんか。

ありがとう。

リチャード

4

4 に答える 4

3

OK、使用している言語やグラフィックス ライブラリに関係なく、このタスクを実行するための一般的なアルゴリズムを次に示します。

  1. 頂点の法線を計算したいと仮定します。つまり、頂点ごとに 1 つの法線になることになります。
  2. 65000 の頂点位置に加えて、メッシュ内の三角形を定義するインデックスのリストがあると仮定しています。たとえば、メッシュ内の三角形 1 は頂点 3、7、および 24 で構成されています。三角形リストまたはストリップまたはメッシュ面の他の説明がありますが、それらはすべて基本的に同じことになります。これらは、特定の面にある頂点を決定するための何らかの方法を説明しています。このような方法の違いは、多くの場合効率に関連していますが、このアルゴリズムの背後にある基本的な考え方は実際には変わりません。
  3. 最初に行う必要があるのは、メッシュ内の各三角形の法線を計算することです。頂点位置ベクトル a、b & c を持つ三角形の場合、三角形の 2 つのエッジのエッジ ベクトルを計算します (例: edge1 = b - a、edge2 = c - a)。次に、これら 2 つのベクトルの外積をとって、この三角形の法線ベクトルを取得します。外積の結果は、正規化する必要があるベクトルです。
  4. すべての三角形の法線が計算されると、頂点の法線は、頂点が属する各三角形の法線を平均することによって計算されます。法線の単純な重み付けされていない平均を行うことができます。つまり、頂点が法線 n1、n2、n3 を持つ 3 つの面の一部である場合、頂点法線は単純に (n1 + n2 + n3)/3 になります。また、加重平均を行うこともできます。この場合、合計の各三角形の法線は、その三角形の面積などの重要な要素によって重み付けされます。ここには正しい方法はなく、さまざまなことをいじることができます。いずれにせよ、平均が計算されたら、それを正規化する必要もあります。ただし、3 つのベクトル n1、n2、n3 の場合、normalized(n1 + n2 + n3) == normalized((n1 + n2 + n3)/3) であるため、これは 1 ステップで実行できます。

さて、これはこれを行うために何を達成する必要があるかについての大まかな説明であることを強調しなければなりません。効率のためにカットできる特定のコーナーがあります。私が理解しているのは、最初にすべての三角形の法線を計算してから、すべての頂点の法線を計算する必要はないということです.2つのステップを組み合わせて、より効率的にすることができます。

一部の疑似コードは次のようになります

Vector verts[65000];         // 65000 vertex positions
Triangle faces[87000];       // as an example, 87000 triangles
Vector normals[65000];       // 1 normal per vertex - initialised to (0, 0, 0)

// loop over all faces to calculate vertex normals
for (int i=0 ; i<87000 ; i++)
{
    Vector v1 = verts[faces[i].vertex1];
    Vector v2 = verts[faces[i].vertex2];
    Vector v3 = verts[faces[i].vertex3];

    Vector edge1 = v2 - v1;
    Vector edge2 = v3 - v1;
    Vector normal = edge1.CrossProduct(edge2);  // or edge2.CrossProduct(edge1)
    normal.Normalise();

    normals[faces[i].vertex1] += normal;
    normals[faces[i].vertex2] += normal;
    normals[faces[i].vertex3] += normal;
}

// vertex normals need to be normalised
for (int i=0 ; i<65000 ; i++)
{
    normals.Normalise();
}

ワインディング オーダーに関する他のコメントについて - これを間違えると、法線は外側ではなく内側を指します。これは、上記のようにクロス積の順序を変更するだけで修正できます。

于 2009-11-22T00:36:08.703 に答える
0

あなたはインデックスを持っているので、私はそれが三角形のリスト/ストリップまたはファンのいずれかであると想定しています。各三角形を読んでください。三角形のベクトルの2つの外積をとって、法線を計算します。ただし、1つの問題があります。三角形の巻き順序がわからない場合は、逆の値になる可能性があります。どのソフトウェアがメッシュを作成しましたか?データファイルまたはソフトウェア内で、巻き取り順序を調べることができますか?左利きですか右利きですか?

于 2009-11-22T00:21:44.773 に答える
0

必要なのは、単位ベクトルに正規化された、三角形の 2 つの辺を構成するベクトルの外積だけです。

Andrew Keith がコメントで述べたように、「外側」から三角形を見ると、三角形は時計回りまたは反時計回りのいずれかで定義されることを知っておく必要があります。一貫性を保証できない場合は、混乱が生じます。しかし、おそらく (または少なくともうまくいけば) オブジェクトを作成したコードは正気です。

于 2009-11-22T00:26:17.807 に答える
0

Steg の答えは正しい方向を示しています。ただし、高品質の法線が必要な場合は、論文Discrete Differential-Geometry Operators for Triangulated 2-Manifolds を参照してください。コタンジェントの式 (8) は、三角形の面積などの推定値が崩れる不規則なメッシュでも良好な結果をもたらします。

于 2009-11-23T01:16:39.870 に答える