図形の選択

2010年1月6日

ファイル

25-picking.tar.gz

使い方

マウスで図形をクリックすると色が変わります。

見所

図形が重なったところをクリックすると、該当する図形すべてがヒットします (ヒット数はコンソール上に表示されます)。一番手前にある図形が選択されるようにしているので、重なった部分をクリックすると、手前にある三角形の色が変わります。

内容

図形の選択を行ってみましょう。ウインドウがクリックされたら、pick() にマウスの位置が渡されます。pick() の処理の流れは、セレクトバッファを用意し、セレクトモードに設定し、クリック周囲のをピック領域として指定し、普通に描画し、ヒット情報を得る、という感じです。セレクトモードで図形を描くとピック領域に描かれる図形のヒット情報が得られる、ということです。

	glSelectBuffer(SELECT_BUFFER_SIZE, selectBuffer);
	glRenderMode(GL_SELECT);

セレクトバッファの用意と、セレクトモードへの設定です。

	glInitNames();
	glPushName(0);

どの図形がピックされたかを示すために、図形に名前をつけるのですが、上はその名前の初期化と、名前を入れ子にするためのスタックの設定です。ここでは名前を入れ子にしませんので、一つだけ適当にスタックにプッシュしています。

	gluPickMatrix(x, vp[3] - y, 5., 5., vp);

ピック領域の指定です。第 1, 2 引数はウインドウ座標です。第 3, 4 引数は幅と高さで、クリック位置に広がりを持たせて選択しやすくしています。

	draw(GL_SELECT);

セレクトモードで描画するよ、と引数で教えつつ描画させます。draw() の中では、以下のようになっています。

	if(mode == GL_SELECT) glLoadName(1);
	...
	if(mode == GL_SELECT) glLoadName(2);
	...

これは、セレクトモードの場合、描くものに 1, 2 ... と名前を付けながら描画することになります。

	hits = glRenderMode(GL_RENDER);

最後に、セレクトモードを抜けるときに、ヒット数が得られます。

	select = selectHits(hits, selectBuffer);

セレクトバッファにヒットの情報が入っていますので、selectHits() でそれを取り出します。

selectHits() の中は以下のようになっています。

	p = buffer;

	for(i = 0; i < hits; i++){
		names = *p++;
		depth1 = *p++;
		depth2 = *p++;
		
		if(depth > depth1){
			depth = depth1;
			select = *p;
			p += names;
		}
	}
	
	return select;

これは、一番手前にあるものを選ぶという処理です。デプスバッファは、ヒットしたものの名前の数 (これは名前を入れ子にした場合に問題になる)、ものの手前の位置、奥の位置、入れ子にしたものの情報…というように情報が並んでいます。手前の位置が最小になるものを見つけることで、クリックした位置の一番手前の図形を選んでいます。

OpenGL プログラミング 目次へ