0

OpenGL用にGLFW3とGLEWでVC++2010を使用しています。三角メッシュをロードするための OBJ-Loader を作成しました。ある時点で、次の配列を VBOMesh2 オブジェクトに入力します。

GLfloat *vertices;
GLfloat *normals;
GLuint *indices;

その結果、VBOに使用するデータを取得します:

  • 頂点 : 頂点 = [v0x、v0y、v0z、v1x、v1y、v1z、...]
  • (ソート済み) 法線 : 法線 = [n0x, n0y, n0z, n1x, n1y, n1z, ...]
  • インデックス : inices = {face0i0, face0i1, face0i2, face1i0, face1i1, face1i2, ...]

次のステップは、バッファを VBOMesh2 オブジェクトの init() メソッドにバインドすることです。vertexVBOID、normalsVBOID、indexVBOID は Gluint です。

void VBOMesh2::init(void)
{
    vertexVBOID = 0;
    glGenBuffers(1, &vertexVBOID);
    glBindBuffer(GL_ARRAY_BUFFER, vertexVBOID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*numFaces*3*3, vertices, GL_STATIC_DRAW);

    normalsVBOID = 0;
    glGenBuffers(1, &normalsVBOID);
    glBindBuffer(GL_ARRAY_BUFFER, normalsVBOID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*numFaces*3*3, normals, GL_STATIC_DRAW);

    indexVBOID = 0;
    glGenBuffers(1, &indexVBOID);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBOID);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*numFaces*3, indices, GL_STATIC_DRAW);

}

わかりました...そして私は次で描きます:

void VBOMesh2::draw(void)
{
    glEnableClientState(GL_VERTEX_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER, vertexVBOID);
    glVertexPointer(3, GL_FLOAT, sizeof(float)*3, 0);

    glEnableClientState(GL_NORMAL_ARRAY);
    glBindBuffer(GL_ARRAY_BUFFER, normalsVBOID);
    glNormalPointer(GL_FLOAT, sizeof(float)*3, 0);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexVBOID);

    glPushMatrix();
    glTranslatef(x, y, z);
    glRotatef(rx, 1, 0, 0);
    glRotatef(ry, 0, 1, 0);
    glRotatef(rz, 0, 0, 1);

    glDrawArrays(GL_TRIANGLES, indices[0], numIndices);

    glPopMatrix();

    glDisableClientState(GL_NORMAL_ARRAY);
    glDisableClientState(GL_VERTEX_ARRAY);
}

次の方法でメッシュをロードできます。

OBJLoader objLoader;
MeshData meshData;
objLoader.loadFile("temp/quad_smooth.obj");
meshData = objLoader.getMeshData();
VBOMesh2 tmpMesh(meshData);

そしてそれを(openGL-Loopで)次のように描画します:

tmpMesh.draw();

次の結果が得られます。

1 つのクワッド

素晴らしい!

今私は考えました、次のコードで500個のクワッドを描きましょう:

OBJLoader objLoader;
MeshData meshData;
objLoader.loadFile("temp/quad_smooth.obj");
meshData = objLoader.getMeshData();

for(int i = 0; i < 500; i++)
{
   VBOMesh2 tmpMesh(meshData);

   meshes.push_back(tmpMesh);
   meshes[i].init();

 // Do stuff for position and rotation like meshes[i].setX(x); and so on
}

そしてopenGL-loopで私は:

for(int i = 0; i < meshes.size(); i++) 
{
   meshes[i].draw();
}

ところで。meshes はベクトルです:

vector<VBOMesh2> meshes;

そして、私は次の結果を得ました:

500 クワッド

大野!!!

そして今、なぜメッシュ (すべてではなく一部) が壊れているのか、または何が間違っているのかについて意見がありません.... コードは視覚化エラーなしで 1 つのクワッドをレンダリングできますが、作成すると同じメッシュデータ (oneQuad からの同じデータ) を持つ 500 個のクワッド 壊れたクワッドを取得しました....

使用する代わりに

glDrawArrays(GL_TRIANGLES, indices[0], numIndices);

私はもう試した

glDrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_INT, 0);

そのために、配列の頂点、法線、インデックスを他の方法で埋めました(必要に応じて投稿できます)が、同じ問題が発生しました...エラーなしで1つのクワッドを描画できますが、500を描画しようとするとQuads でアクセス違反 0x000005 が発生しました。

ところで。グラフィックカードのドライバーを更新しました(ただし、問題は残ります)

誰かが私にヒントを与えることができますか?

4

1 に答える 1

0

std::vector<VBOMesh2>ベクトルは値を操作するため、は使用しないでください。~VBOMesh2配列を削除するように実装した場合は、ダングリング ポインター (つまりindices[0]) を描画している可能性があります。VBOMesh2または の単純な配列を使用しstd::vector<VBOMesh2*>ます。

glDrawArrays(GL_TRIANGLES, indices[0], numIndices);

これは、インデックス付きメッシュを描画する方法ではありません。glVertexPointer2 番目のパラメーターは、前におよび でバインドした配列へのオフセットですglNormalPointer。あなたの場合、それは常に0でなければなりません。

インデックス付きメッシュを使用するかどうかを決定する必要がありますが、それについての質問は明確ではありません。その場合は、 を使用する必要がありますglDrawElements。ただし、頂点と法線データのサイズが適切ではありません。しかし、あなたはそれを知っていると思います。インデックス付きメッシュのコードを最初に実装し、それが機能しなかったときにインデックスなしメッシュに変換しようとしたようです。

于 2013-07-21T19:10:27.737 に答える