2011-12-05 30 views
4

Appleのサンプルコードに基づいて、OpenGL-ESでかなり基本的な形状を作っています。彼らは、最初の配列へのインデックスの配列を持つ点の配列を使用し、3つのインデックスの各セットはポリゴンを作成します。それはすべて素晴らしいです、私は私が望む形を作ることができます。シェイプを正しくシェイプするには、各ポリゴンの各頂点の法線を計算する必要があると思います。最初は形状が直方体なので非常に簡単でしたが、私はこれらの法線を自動的に作成したいと考えています。ポリゴンの2つの辺のベクトル(すべてのポリゴンはここでは三角形です)を取得し、そのポリゴンのすべての頂点にそのクロス積を使用すれば十分です。その後、私は形状を描くために以下のようなコードを使用します。GLKit/OpenGL-ESで法線を自動的に計算する

glEnableVertexAttribArray(GLKVertexAttribPosition); 
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, triangleVertices); 

glEnableVertexAttribArray(GLKVertexAttribColor); 
glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, 0, triangleColours); 

glEnableVertexAttribArray(GLKVertexAttribNormal); 
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 0, triangleNormals); 

glDrawArrays(GL_TRIANGLES, 0, 48); 

glDisableVertexAttribArray(GLKVertexAttribPosition); 
glDisableVertexAttribArray(GLKVertexAttribColor); 
glDisableVertexAttribArray(GLKVertexAttribNormal); 

私はこれを手動で行う必要がある理由を理解しています。私は、サーフェスに垂直なベクトル以外のものが必要な場合があると確信していますが、これがもっともポピュラーなユースケースであることも確信しています。明白な何かを逃したことがありますか? glCalculateNormals()は素晴らしいでしょう。

//答えは以下の通りです 法線で塗りつぶしたいGLKVector3 []を渡します。もう1つは頂点(それぞれ3つはポリゴンにグループ化されています)と頂点の数です。

- (void) calculateSurfaceNormals: (GLKVector3 *) normals forVertices: (GLKVector3 *)incomingVertices count:(int) numOfVertices 
{ 

    for(int i = 0; i < numOfVertices; i+=3) 
    { 
     GLKVector3 vector1 = GLKVector3Subtract(incomingVertices[i+1],incomingVertices[i]); 
     GLKVector3 vector2 = GLKVector3Subtract(incomingVertices[i+2],incomingVertices[i]);   
     GLKVector3 normal = GLKVector3Normalize(GLKVector3CrossProduct(vector1, vector2)); 
     normals[i] = normal; 
     normals[i+1] = normal; 
     normals[i+2] = normal; 
    } 
} 

答えて

2

そして再び答えは:OpenGLはシーン経営管理論ライブラリやジオメトリライブラリでもないですが、画面に素敵な絵を描くだけで描画API。照明のためには法線が必要であり、それに法線を与えます。それで全部です。なぜなら、これは単にユーザーが行うことができ、実際の描画とは何の関係もない場合、法線を計算するのはなぜですか?

とにかく実行時には計算しないでくださいが、ファイルからロードすることはよくあります。そして、法線を計算する多くの方法があります。面ごとの法線または頂点ごとの法線が必要ですか?特定のハードエッジや特定の滑らかなパッチが必要ですか?頂点の法線を平均化して頂点の法線を取得する場合、これらの平均をどのようにしたいですか?

そして、新しいOpenGLバージョンでは、シェーダーの出現と組み込みの通常の属性とライティング計算の削除によって、この全体的な質問はあなたの望むように照明でき、従来の法線はもはや必要ないので、 。

ところで、あなたは顔ごとの法線を使用しているように聞こえます。つまり、顔のすべての頂点が同じ法線を持つようになります。これは、ハードエッジを持つ非常にファセットのモデルを作成し、インデックスと一緒にうまく機能しません。スムーズなモデルが必要な場合(私には分かりませんが、実際にはファセット面が必要な場合もあります)、各頂点の隣接する面の法線を平均して頂点ごとの法線を計算する必要があります。これは、実際にはより一般的なユースケースであり、顔ごとの法線ではありません。

だから、この擬似コードのような何かを行うことができます:

for each vertex normal: 
    intialize to zero vector 

for each face: 
    compute face normal using cross product 
    add face normal to each vertex normal of this face 

for each vertex normal: 
    normalize 

は滑らか頂点ごとの法線を生成します。実際のコードでさえ、これは10行から20行の間のコードになります。これは実際には複雑ではありません。

+0

私は自分のケースが大部分のケースだと思っていましたが、それが通常どのように行われていない場合、私はそれが手動の仕事であることを理解することができます。私は主にブロックが欲しいので、私はおそらく私のシステムに固執するでしょう。私は12のポリゴンと36の頂点を持っていますが、私は8つの法線しか計算していませんが、OpenGLにどのように伝えるのですか?頂点に合わせるために36の法線の配列が必要ですか?法線を同じ順序で配置しますか?これは、2つのポリゴンが頂点を共有するとき、またはノーマルと頂点をリンクする方法が存在するときに繰り返されるものがあることを意味しますか? – Craig

+0

@Craig常に頂点ごとに1つの法線があります。法線を計算する場合(面単位)、面の各頂点ごとに各面法線を繰り返す必要があります。頂点ごとの法線を計算すると、頂点が実際に頂点と同じように各頂点の法線が繰り返されます。概念的には、頂点はその属性すべてであり、位置だけでなく、残念なことに頂点とも呼ばれるOpenGLである。 –

+0

@Craigしかし、頂点ごとの法線(ストレージ効率に関して)の利点は、各一意の頂点が同じ法線を持つため、インデックス配列(および 'glDrawElements')を使用して重複を完全に減らすことができるということです。ユニークな位置を持つ各頂点が複数の異なる法線を持つ可能性があるため、面ごとの法線では、インデックスは何も購入しません。なぜなら、とにかに頂点を複製する必要があるからです。 –

関連する問題