OpenGLのヒットレコードの解析はわかってしまえば簡単なのだが、わかっていてもなお、ゼロからコード書いてテスト通過するまではなかなか厄介なものだ。ヒットしたレコードの中で最も手前にあるものはどれかと探したいだけなのに。。
そこで、今回は、OpenGLのヒットレコード解析をとても簡単にしてくれる、解析クラスの紹介だよ。その名もnurs::glHitRecordsだ。
struct glHitRecords; struct glHitRecord { friend class glHitRecords; glHitRecord(){} ~glHitRecord(){} POC_PROP( float, _minz, MinZ ); POC_PROP( float, _maxz, MaxZ ); POC_PROP( vector< int >, _name_vec, NameVec ); }; struct glHitRecords { glHitRecords( const int num_hits, const GLuint* selbuf ) { vector< glHitRecord* >& l = this->_hitrecord_vec; const GLuint* p = selbuf; for( int i=0; i<num_hits; ++i ) { glHitRecord* hit = new glHitRecord(); { hit->setMinZ( (float)p[1] / 0x7fffffff ); hit->setMaxZ( (float)p[2] / 0x7fffffff ); hit->refNameVec().reserve( p[0] ); for( int j=0; j<p[0]; ++j ){ hit->refNameVec().push_back( p[3+j] ); } p += (3+p[0]); } l.push_back( hit ); }// i sort( l.begin(), l.end(), mem_comp( &glHitRecord::_minz ) ); } ~glHitRecords( void ){ POC_FOREACH( _hitrecord_vec, glHitRecord* ihit ){ delete ihit; }// } const glHitRecord* NearbyHit( void ) const{ return this->_hitrecord_vec.empty() ? 0: this->_hitrecord_vec.front(); } POC_PROP( vector< glHitRecord* >, _hitrecord_vec, HitRecordVec ); };
おっと、POC_PROPについてはこちらを、そしてmem_compについては、一つ前の日記を参照してくれ。mem_compは実は今回ここで使うための前振りだったのさ。NURS_FOREACHについては別にBOOST_FOREACHでも何でもいいのだが気になる人はこちらを見てくれ。
さてnurs::glHitRecordsだ。使い方はとても簡単、
int nhits = glRenderMode( GL_RENDER ); glHitRecords hrs( nhits, selbuf );// ★ // ここでは、最近傍のヒットレコードの中の、2番目のネームスタック階層のネームを取得してみよう。 glHitRecord* hr = hrs->NearbyHit(); if( hr ){ if( hr->NameVec().size() >1 ){ const GLuint& first_hit_name = hr.NearbyHit()->NameVec()[1]; } }
glSelectBufferに指定した選択バッファと、glRenderMode( GL_RENDER ) の返値としてゲットしたヒット数を指定して、nurs::glHitRecords のインスタンスを作成する。これだけで、glHitRecords の内部では、ヒットレコードを、その最小Z値の小さい順でソートして内部情報として再構築してくれる。
あとはこのインスタンスについて、NearbyHit()メソッドを呼び出すだけで、Z値の最も小さい最近傍ヒットレコードを得る。