あかすくぱるふぇ

同人サークル「あかすくぱるふぇ」のブログです。

下記記事の実例。
ググればいくらでも出てくる内容だけど、整理しておきたかったので。
http://akasuku.blog.jp/archives/44623464.html

○単純な四角形の描画
以下が置き換え前。
GLdouble vertices[sizeOfVertices] = {
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0
};

void scene()
{
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
for (int i = 0; i < vertexNum; ++i) {
glVertex3d(vertices[i * dimNum], vertices[i * dimNum + 1],
vertices[i * dimNum + 2]);
}
glEnd();
}
VBOで置き換えると以下のようになる。
GLdouble vertices[sizeOfVertices] = {
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0
};
GLuint vrtVBO;

void init()
{
// バッファの生成
glGenBuffers(1, &vrtVBO);

// 頂点位置の転送
glBindBuffer(GL_ARRAY_BUFFER, vrtVBO);
glBufferData(GL_ARRAY_BUFFER, sizeOfVertices * sizeof(GLdouble),
vertices, GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void scene()
{
// 頂点位置のデータ位置の指定
glBindBuffer(GL_ARRAY_BUFFER, vrtVBO);
glVertexPointer(dimNum, GL_DOUBLE, 0, 0);

// 描画
glEnableClientState(GL_VERTEX_ARRAY);
  glColor3f(1.0f, 0.0f, 0.0f);
 glDrawArrays(GL_QUADS, 0, vertexNum);
glDisableClientState(GL_VERTEX_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, 0);
}

○テクスチャマッピング
以下が置き換え前。
GLdouble vertices[sizeOfVertices] = {
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0
};
GLdouble texCoords[sizeOfTexCoords] = {
0.0, 1.0,
1.0, 1.0,
1.0, 0.0,
0.0, 0.0
};

void scene()
{
glEnable(GL_TEXTURE_2D);

glBegin(GL_QUADS);
for (int i = 0; i < vertexNum; ++i) {
glTexCoord2d(texCoords[i * 2], texCoords[i * 2 + 1]);
glVertex3d(vertices[i * dimNum], vertices[i * dimNum + 1],
vertices[i * dimNum + 2]);
}
glEnd();

glDisable(GL_TEXTURE_2D);
}
VBOで置き換えると以下のようになる。
GLdouble vertices[sizeOfVertices] = {
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0
};
GLdouble texCoords[sizeOfTexCoords] = {
0.0, 1.0,
1.0, 1.0,
1.0, 0.0,
0.0, 0.0
};
GLuint vrtVBO;
GLuint uvVBO;

void init()
{
// バッファの生成
glGenBuffers(1, &vrtVBO);
glGenBuffers(1, &uvVBO);

// 頂点位置の転送
glBindBuffer(GL_ARRAY_BUFFER, vrtVBO);
glBufferData(GL_ARRAY_BUFFER, sizeOfVertices * sizeof(GLdouble),
vertices, GL_STATIC_DRAW);

// UV座標の転送
glBindBuffer(GL_ARRAY_BUFFER, uvVBO);
glBufferData(GL_ARRAY_BUFFER, sizeOfTexCoords * sizeof(GLdouble),
texCoords, GL_STATIC_DRAW);

glBindBuffer(GL_ARRAY_BUFFER, 0);
}

void scene()
{
// 頂点位置のデータ位置の指定
glBindBuffer(GL_ARRAY_BUFFER, vrtVBO);
glVertexPointer(dimNum, GL_DOUBLE, 0, 0);

// UV座標のデータ位置の指定
glBindBuffer(GL_ARRAY_BUFFER, uvVBO);
glTexCoordPointer(2, GL_DOUBLE, 0, 0);

// 描画
glEnableClientState(GL_VERTEX_ARRAY);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glDrawArrays(GL_QUADS, 0, vertexNum);
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, 0);
}
○VAO
ついでに、VAOへ置き換えると以下のようになる。
GLdouble vertices[sizeOfVertices] = {
-1.0, -1.0, 0.0,
1.0, -1.0, 0.0,
1.0, 1.0, 0.0,
-1.0, 1.0, 0.0
};
GLdouble texCoords[sizeOfTexCoords] = {
0.0, 1.0,
1.0, 1.0,
1.0, 0.0,
0.0, 0.0
};
GLuint vrtVBO;
GLuint uvVBO;
GLuint vao;

void init()
{
// VAOの生成
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

// VBOの生成
glGenBuffers(1, &vrtVBO);
glGenBuffers(1, &uvVBO);

// 頂点の位置と設定の転送
glBindBuffer(GL_ARRAY_BUFFER, vrtVBO);
glBufferData(GL_ARRAY_BUFFER, sizeOfVertices * sizeof(GLdouble),
vertices, GL_STATIC_DRAW);
glVertexPointer(dimNum, GL_DOUBLE, 0, 0);
glEnableClientState(GL_VERTEX_ARRAY);

// UV座標の転送
glBindBuffer(GL_ARRAY_BUFFER, uvVBO);
glBufferData(GL_ARRAY_BUFFER, sizeOfTexCoords * sizeof(GLdouble),
texCoords, GL_STATIC_DRAW);
glTexCoordPointer(2, GL_DOUBLE, 0, 0);
glEnable(GL_TEXTURE_2D);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}

void scene()
{
glBindVertexArray(vao);
glDrawArrays(GL_QUADS, 0, vertexNum);
glBindVertexArray(vao);
}

PMX(MMDモデル)ファイルビューワーの制作で必要になったので。

PMXファイル内の文字列はUTF-8とUTF-16のどちらかで書かれている。
どちらで書かれているかはヘッダで判断できる。
つまり、ヘッダに応じて、UTF-8とUTF-16のどちらで読むかの場合分けが必要となる。

その違いを吸収するための関数を作ってみた。
typedef std::basic_string<TCHAR, std::char_traits<TCHAR>, std::allocator<TCHAR> > tstring;

tstring read(std::ifstream& fileStream, const int size)
{
tstring str;

WCHAR wcharTmp[MAX_CHAR_LENGTH];
fileStream.read(reinterpret_cast<char*>(&wcharTmp), size);

// 終端文字付きの文字列を得るためにstringを利用。
// stringは終端文字を持たない代わりに、size()関数で文字列の長さを保持する。
// そして、c_str()で終端文字付の文字列配列を返す。
std::wstring wstr = wcharTmp;
wstr.resize(size / 2);
#ifdef _UNICODE
str = wstr;
#else
char charTmp[MAX_CHAR_LENGTH];
int multiByteSize = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), -1, NULL, 0, NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, wcharTmp, -1, charTmp, multiByteSize, NULL, NULL);
str = charTmp;
str.resize(multiByteSize - 1);
#endif

return str;
}
参考ページ
http://d.hatena.ne.jp/sirocco/20130418/1366253252

個人的な備忘録として。

Visual Studioでは、Unicodeとマルチバイト文字に両対応するためのTCHARという型がある。
文字列を扱う時には基本的にTCHARを使うことになるが、

"1byteずつファイルから読み込みたい"
といった場合に以下のようにしてはいけない。

TCHAR hoge;
ifs.read(hoge, sizeof(TCHAR));
こうしてしまうと、
"マルチバイト文字セットを使用する場合は1バイトずつ、Unicode文字セットを使用する場合は2バイトずつ読み込む"
といった処理になってしまう。

1バイトずつ読み込みたいなら使用文字セットに関わらず、charを使う必要がある。

↑このページのトップヘ