web-dev-qa-db-ja.com

std :: vectorを使用したVBO

OpenGLのC++でモデルローダーを記述しました。頂点データを格納するために_std::vector_ sを使用しましたが、これをglBufferData()に渡したいのですが、データ型が大きく異なります。 _std::vector_をドキュメント化された_const GLvoid *_からglBufferData()に変換する方法があるかどうか知りたい。

頂点タイプ

_typedef struct
{
    float x, y, z;
    float nx, ny, nz;
    float u, v;
}
Vertex;

vector<Vertex> vertices;
_

glBufferData()呼び出し

_glBufferData(GL_ARRAY_BUFFER, vertices.size() * 3 * sizeof(float), vertices, GL_STATIC_DRAW);
_

次の(予期される)エラーが発生します。

_error: cannot convert ‘std::vector<Vertex>’ to ‘const GLvoid*’ in argument passing
_

ベクターをglBufferData()と互換性のある型に変換するにはどうすればよいですか?

現時点では、正しいメモリ割り当ては気にしていません。vertices.size() * 3 * sizeof(float)はsegfaultの可能性が高いですが、タイプエラーを最初に解決したいと思います。

37
Bojangles

std::vector<T> vがある場合は、式T*を使用して、連続するデータ(OpenGLの後に続くデータ)の開始を指す&v[0]を取得できます。


あなたの場合、これはVertex*glBufferDataに渡すことを意味します:

glBufferData(
   GL_ARRAY_BUFFER,
   vertices.size() * sizeof(Vertex),
   &vertices[0],
   GL_STATIC_DRAW
);

またはこれは同じです:

glBufferData(
   GL_ARRAY_BUFFER,
   vertices.size() * sizeof(Vertex),
   &vertices.front(),
   GL_STATIC_DRAW
);

ここでは、Vertex*からvoid const*への暗黙的な変換を利用できます。それは問題にならないはずです。

これでうまくいくはずです:

_&vertices[0]
_

一部の人は&vertices.front()を好みますが、それはよりタイピングが多く、私は骨の折れる仕事です。

さらに遅延させるには、glBufferDataをオーバーロードすることができます。

_template <class T>
inline void glBufferData(GLenum target, const vector<T>& v, GLenum usage) {
    glBufferData(target, v.size() * sizeof(T), &v[0], usage);
}
_

それからあなたは書くことができます:

_glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
_

また、バグを回避します(構造体が3 * sizeof(float)より大きい)。

27
Marcelo Cantos