簡易OpenGL選択バッファ解析

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値の最も小さい最近傍ヒットレコードを得る。