3

Maya で 1 分間のアニメーションを作成しており、それを OpenGL でレンダリングするつもりです。私はこれを大学でのプロジェクトとしてやっています。

シーンは、歪んだ表情をしている人間の顔だけで構成されています。メッシュには約 2200 のクワッド フェースがあります。

Wavefront オブジェクト ファイルを頂点配列と法線配列に変換する perl スクリプトを見つけました。Maya で 24 fps でアニメートし、すべてのフレームのメッシュを Wavefront オブジェクト ファイルにエクスポートし、それらすべてを perl スクリプトで実行して、頂点と法線の配列を取得します。

そのため、実現可能性をテストするために、Maya のアニメーションの 2 つのフレームをオブジェクト ファイルに変換し、(微調整した後に) スクリプトを実行したところ、数千のglVertexandglNormal呼び出しが得られました。そのすべてを C++ プログラムにコピーしてコンパイルしました。それはスムーズに実行されます。

プログラムに 60sec*24frame 分のglVertexandglNormalステートメントをコピーすると、プログラムがどれだけ大きくなるかを考えて、VBO を使用してみます。それで、私はそれについて読みましたが、実装を完全に把握していません。

したがって、私の最初の質問は次のとおりです。この場合、VBO を実装する最良の方法は何ですか?

頂点と法線の両方の 2D 配列を、フレームごとに 1 つずつ考えています。のGL_STATIC_DRAW_ARB「使用法」パラメータについては、glBufferDataARB().

たとえば、アニメーションの長さが 5 フレームで、顔のメッシュが 2200 の頂点と法線で構成されている場合、次のように作成します。

GLfloat face_vertices[5][2200] = {.....};
GLfloat face_normals[5][2200] = {.....};

私の 2 番目の質問: 上記のコードは VBO で機能するか、「うまく」実行されますか?

また、この情報が重要かどうかはわかりませんが、私のコンピューターは Intel 82945G グラフィック カードで実行されており、大学の PC も Intel で実行されていると確信しています。私はそれについて言及したいと思っただけです。

アップデート

パフォーマンスも懸念事項です。

4

2 に答える 2

1

アニメーションの 2 フレームをスムーズに実行できた場合、Maya アニメーションから GL 呼び出しを自動的に生成できれば、「glVertex および glNormal ステートメントに相当する」60*24 フレームをスムーズに実行できます。このアプローチの唯一の問題は、ソース コードとバイナリ実行可能ファイルが非常に巨大になることです。これは、あなたのアプローチを「悪い」ものにする問題です。

したがって、まず、すべての頂点データに対して 1 つの glVertex 呼び出しを行う代わりに、データを配列 (または std::vector) に格納し、単純なループを使用してそれを反復処理することができます。

std::vector<int> idx;
std::vector<vertex> frame_data;
...
glBegin(GL_QUADS);
for(int i = 0; i < idx.size(); ++i) {
  glVertex3f(frame_data[idx].x, frame_data[idx].y, frame_data[idx].z);
  glNormal3f(frame_data[idx].nx, frame_data[idx].ny, frame_data[idx].nz);
}
glEnd();

Idx は面を表し、idx の各 4 つの要素がクワッドを形成します。Frame_data はそのフレームの特定の頂点データです。フレームごとにそのような配列が 1 つ必要であり、このデータは idx によってインデックス付けされます。このように、解決しなければならない唯一の問題は、このデータをアプリケーションに読み込む方法です。メッシュ ファイルから glVertex 呼び出しを生成できる場合は、代わりに、C++ fstream を使用してアプリケーション内に簡単にロードできるファイルを生成し、データの配列を構築してから、それらを反復処理して描画呼び出しを行うことができます。

この場合、glBegin()/glEnd() を使用した場合と VBO を使用した場合のパフォーマンスの違いはわかりません。2200 のクワッドは数が少なすぎて違いがありませんが、興味深い演習になるでしょう。先ほどお伝えした配列 (idx と vertex_data) 内のデータを整理することが、VBO を使用するための最初のステップです。単一の構造内の 1 つの頂点に関連するすべてのデータをパックする必要があります。

struct vertex {
  float x, y, z; // Position
  float nx, ny, nz; // Normal
};
...
vertex frame_data[v_count];
uint16_t idx[2200 * 4]; // 4 vertices makes one face

v_count が 2200 ではないことに注意してください。これはクワッド カウントであるため、この数値は frame_data ではなく idx サイズに関連しています。つまり、同じ頂点が複数のクワッド フェースで使用されている可能性があります。

idx を保持するための静的バッファ (GL_STATIC_DRAW を使用した GL_ELEMENT_ARRAY_BUFFER) と、頂点データを保持するための別の「ストリーム」バッファ (GL_STREAM_DRAW を使用した GL_ARRAY_BUFFER) の 2 つのバッファが必要になります。最後の例では、アニメーションのためにフレームごとにコンテンツを書き換える必要があるため、「GL_STREAM_DRAW」を使用します。glBufferDataを参照してください。

于 2012-04-22T18:53:05.823 に答える
1

頂点と法線の両方の 2D 配列を、フレームごとに 1 つずつ考えています。と

それは間違った解決策だと思います。この量のデータをストリーミングするのは理にかなっています。たとえば、アニメーションの 1 秒をメモリに保持し、残りをオンデマンドでロードします。GL_STREAM_****このシナリオにはフラグがあると思います。

より良い解決策は、Maya とそのアニメーションからボーンをエクスポートすることです。(この場合、変更されないメッシュが 1 つ必要になります)

フレームごとの頂点アニメーションをエクスポートしなければならない唯一の状況は、非常に計算コストの高いものをエクスポートする場合です。私が考えることができる唯一の現実的なシナリオは、3D 流体メッシュ (トポロジーがフレームごとに変化するなど) です。それ以外はすべて、CPU または GPU で計算できます。ただし、あなたの投稿は、これがあなたのシナリオであることを示していません。したがって、マーフィーの法則により、別の方法で解決できる問題に対して非効率的な解決策を使用していると想定する必要があります。

: 上記のコードは VBO で機能するか、または「うまく」実行されますか?

データをどのように描画するかを言わなかったので、答えられません。単純なジオメトリであっても、シェーダーやアルファ ブレンディングを悪用したり、同じものを何回もレンダリングしたりすることで、どんなマシンでも屈服させることができます。

于 2012-04-22T16:25:46.473 に答える