OpenGL VBOのglMapBuffer関数について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
DOG
記事: 27
登録日時: 10年前

OpenGL VBOのglMapBuffer関数について

#1

投稿記事 by DOG » 10年前

今、VBOの学習をしていているのですが、glMapBuffer関数について良く分かっていません。
まずこちらのwikiに載っているプログラムを見ていただきたいです。(転載していいのかよくわからなかったので、ここには載せていません。ご了承ください。)
http://seesaawiki.jp/w/mikk_ni3_92/d/VB ... a5%c91%5f2

このプログラムの
void display() の中の
//アップデート
と書かれている箇所にglMapBuffer関数が使われています。

このプログラムによって、y軸を中心に回転させているようなのですが、どんな原理になっているのか全然わからないので
どなたかご教授していただけないでしょうか?

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: OpenGL VBOのglMapBuffer関数について

#2

投稿記事 by h2so5 » 10年前

glMapBufferはメインメモリのデータとビデオメモリのデータを同期するための関数です。
glMapBufferの第二引数がGL_READ_WRITEの場合、glMapBufferを呼び出したときにビデオメモリの内容がメインメモリにロードされ、glUnmapBufferを呼び出したときにメインメモリの内容がビデオメモリに書き戻されます。
こうすることでビデオメモリをメインメモリのように操作することができます。

VBOの回転行列を更新することでy軸を中心に回転させています。

DOG
記事: 27
登録日時: 10年前

Re: OpenGL VBOのglMapBuffer関数について

#3

投稿記事 by DOG » 10年前

返答ありがとうございます。
すみません、私の言葉足らずでした。

コード:

glBindBuffer(GL_ARRAY_BUFFER, VboId[0]);
        float *ptr = (float*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
        if(ptr)
        {       
                static float tmp[3];
                for(int loop = 0; loop < aryElemNum;loop += 3)
                {
                        //計算用にコピー
                        tmp[0] = ptr[loop];
                        tmp[1] = ptr[loop+1];
                        tmp[2] = ptr[loop+2];

                        ptr[loop]=cos(PI_OVER_180*angle)*tmp[0] + sin(PI_OVER_180*angle)*tmp[2];
                        ptr[loop+1] = tmp[1];
                        ptr[loop+2]= -sin(angle*PI_OVER_180)*tmp[0]+cos(PI_OVER_180*angle)*tmp[2];
                }
                glUnmapBuffer(GL_ARRAY_BUFFER);
        }
の部分がなぜy軸回転を表しているかというのと、更新というのは、何かもともと行列があってそれを書き変えているということだと思うのですが、
その書きかえられている部分というのはwiki上のプログラムではどこになるのでしょうか?

なかなか言葉で言い表すのは難しいですが、よろしくお願いします。

アバター
へにっくす
記事: 634
登録日時: 11年前
住所: 東京都

Re: OpenGL VBOのglMapBuffer関数について

#4

投稿記事 by へにっくす » 10年前

h2so5さんのレスの繰り返しになりますけど・・・

> なぜy軸回転を表す
cos/sinを使ってる部分がそうなんだなと見当つきませんか。

> もともと行列があってそれを書き換える
掲示されたコードでは、glMapBufferでもともとの行列を取り出していることになるのかな。
なのでptrに値を代入しているところが、実際に更新する処理になっていると思います。
その後、glUnmapBufferでビデオメモリに転送していると。

理解できなかったらすみません。
written by へにっくす

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: OpenGL VBOのglMapBuffer関数について

#5

投稿記事 by ISLe » 10年前

そもそもポインタが分からないということかもしれませんが。

コメントで説明書いてみました。

コード:

	glBindBuffer(GL_ARRAY_BUFFER, VboId[0]);
	// ※※ 以後、GL_ARRAY_BUFFER(頂点バッファ)とはVboId[0]に格納したIDのもの
	float *ptr = (float*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);
	// ※※ 頂点バッファを読み書きするため、メインメモリに割り当て、割り当てたメモリの先頭アドレスが戻る
	if(ptr) // 割り当てに成功していれば真
	{
		static float tmp[3];
		for(int loop = 0; loop < aryElemNum;loop += 3)
		{
			//計算用にコピー
			tmp[0] = ptr[loop];
			tmp[1] = ptr[loop+1];
			tmp[2] = ptr[loop+2];
			// ※※ メインメモリに割り当てられた頂点バッファの指定の位置から値をコピー

			ptr[loop]=cos(PI_OVER_180*angle)*tmp[0] + sin(PI_OVER_180*angle)*tmp[2];
			ptr[loop+1] = tmp[1];
			ptr[loop+2]= -sin(angle*PI_OVER_180)*tmp[0]+cos(PI_OVER_180*angle)*tmp[2];
			// ※※ メインメモリ上で回転した値に書き変える
		}
		glUnmapBuffer(GL_ARRAY_BUFFER);
		// ※※ 頂点バッファの割り当て解除。ビデオメモリ上の頂点バッファがメインメモリ上で書き変えた値に更新される
	}

DOG
記事: 27
登録日時: 10年前

Re: OpenGL VBOのglMapBuffer関数について

#6

投稿記事 by DOG » 10年前

へにっくすさん、ISLeさん返答ありがとうございます。
glMapbufferがどのような役割を果たしているかというのは何となくですが、わかってきました。
実はまだいろいろとすっきりしていないところがあるのですが、とりあえず確実に分からないところがあるのでご教授ください。
それは、どうしてy軸回転を表しているのかという疑問についてですが、cos,sinを使っている部分が回転を表しているという予想はついておりました。
しかし、数学によると3次元でのy軸回転を表す式というのは行列で、
(cosθ 0 -sinθ)
( 0 1 0 ) ←3×3行列です
(sinθ 0 cosθ)
と表されるのですが、プログラム上だとこれが

コード:

ptr[loop]=cos(PI_OVER_180*angle)*tmp[0] + sin(PI_OVER_180*angle)*tmp[2];
ptr[loop+1] = tmp[1];
ptr[loop+2]= -sin(angle*PI_OVER_180)*tmp[0]+cos(PI_OVER_180*angle)*tmp[2];
となっているのがピンとこないわけです・・・・・

DOG
記事: 27
登録日時: 10年前

Re: OpenGL VBOのglMapBuffer関数について

#7

投稿記事 by DOG » 10年前

連投失礼します。
やはり分からないことがもう一つあります。
glGenBuffers,glBindBuffer,glBufferDataをつかって、CPU上の配列データをGPU上にコピーをしていることは分かります。
そして、そのコピーした配列データを
glMapBufferで修正できるようにしているのですよね。

このプログラムで配列データというのは、紛れもなく

コード:

float points[]=
{
        0,1,0,
        -0.5, 0,0,
        0.5, 0,0
};
だと思います。
すなわちこの配列をglMapBufferでy軸回転を表す配列に修正しているということでしょうか?
仮にそうなっているとすれば、VBO上(GPU上)での配列データはy軸回転を表すものになり、これでCPU上の頂点の配列データを使って描画した物体を回転させているということなのでしょうか?

アバター
h2so5
副管理人
記事: 2212
登録日時: 13年前
住所: 東京
連絡を取る:

Re: OpenGL VBOのglMapBuffer関数について

#8

投稿記事 by h2so5 » 10年前

VBOで回転行列を扱っているというのは間違いです。申し訳ありません。
コードをよく見たら座標をそのまま更新していますね。回転行列の演算はCPUで行って、回転後の座標をGPUに直接転送していることになります。

アバター
へにっくす
記事: 634
登録日時: 11年前
住所: 東京都

Re: OpenGL VBOのglMapBuffer関数について

#9

投稿記事 by へにっくす » 10年前

もともとの行列は回転行列じゃないですね。
下記の図を参照してください。
dixq_net_t14651_1.png
あなたの示した回転行列を展開すると。
dixq_net_t14651_1.png (18.11 KiB) 閲覧数: 7620 回
written by へにっくす

DOG
記事: 27
登録日時: 10年前

Re: OpenGL VBOのglMapBuffer関数について

#10

投稿記事 by DOG » 10年前

h2so5さん、へにっくすさん返答ありがとうございます。

なるほど!
ということは頂点座標の配列データを、VBO内でy軸回転させたあとの座標の配列データに修正したということなのですね。
そしてそれを、glDrawArraysで描画したわけですね。

へにっくすさん、数式を解説していただくために画像まで用意してくださってありがとうございました。
大変分かりやすかったです。

ISLe
記事: 2650
登録日時: 13年前
連絡を取る:

Re: OpenGL VBOのglMapBuffer関数について

#11

投稿記事 by ISLe » 10年前

ちなみにVertex Buffer Object(VBO)のvertexが頂点という意味です。
行列はmatrixです。

DOG
記事: 27
登録日時: 10年前

Re: OpenGL VBOのglMapBuffer関数について

#12

投稿記事 by DOG » 10年前

ISLeさん補足説明ありがとうございます。

すみません、やはりもう一つ分からないところが出てきました。
cosとsinの中身にangleが使われていますが、これは1で初期化されています。
PI_OVER_180も定数で、これとangleをかけていることから、単位である「°」を「ラジアン」に変えているのはわかるのですが、
angleの値を変動させてるプログラムは見当たらないので、回転し続けるというアニメーションになる理屈が分かりません。
cos,sinの中身は定数になっているのではないのでしょうか?

アバター
へにっくす
記事: 634
登録日時: 11年前
住所: 東京都

Re: OpenGL VBOのglMapBuffer関数について

#13

投稿記事 by へにっくす » 10年前

全然理解していないですね。
何もイベントがなければ、glutIdleFuncで登録されたidle関数が呼ばれること、
idle関数で常に再描画イベントが呼ばれる(glutPostRedisplay)こと、
glutDisplayFuncで再描画イベントとしてdisplay関数が登録されていること、
display関数が呼ばれるたびにangleごと回転して各頂点の座標が上書きされること。

上書き、というのがポイントですよ。以下の図のようにくるくる回転することになる。
図では8分割ですが、これがangleごとになってると想像してください。1度なんだから360分の1ですね。
dixq_net_t14651_2.png
一回呼ばれるたびに、矢印の方向に頂点の座標が上書きされる。
dixq_net_t14651_2.png (11.88 KiB) 閲覧数: 7534 回
written by へにっくす

DOG
記事: 27
登録日時: 10年前

Re: OpenGL VBOのglMapBuffer関数について

#14

投稿記事 by DOG » 10年前

へにっくすさん、返答ありがとうございます。
確かに、じっくり考えてみるとangleそのものを変動させる必要なんかないですね。
同じ角速度で回転しているのだったら当たり前のことでした・・・
最後まで私の質問にお付き合いしていただき、ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る