フォトンマップを作った後、実際に描画するときに放射輝度を求めるために視点からの交点近辺のフォトンを取り出す必要がある。 この処理を高速に行うためにはkd-treeを使うといい、という話。
でもいきなり3D用のkd-treeのルーチンを書いて動かせる自信がない…なので2Dのテストプログラムを作る。
kd-treeの構築
- 木をバランスさせるため、フォトンを記録し終わってから構築する
- 分割する軸を選ぶ(x,y,zで一番長い軸にしてみた)
- 分割軸に沿ってソート
- 左右でバランスするように、左右の要素数を決める(葉が左詰になって欲しいので、あれこれ計算)
// 木を分割する中央のインデクスを求める |
- 0オリジンの場合、ノードiの子供はi2+1とi2+2
- 再帰的に繰り返す
- 分割するたびにソートしなおすので、クイックソートがO(n logn)として、O(n log^2(n))?
近傍要素の探索
- ツリーの根から始めて、含まれるほうの枝は必ず見て、含まれないほうの枝は最大距離以内だったら見る
- 今までに見つかった近傍要素中の最大距離を更新していく
// 「フォトンマッピング」本6.4 最近傍フォトンの効率的発見、locate_photons()参照 |
- バランスしてれば O(log(n))
雑多
- フォトンマップの場合、空間にある程度ばらけて分布するのではなく、壁などの表面に偏って分布するだろうからkd-treeがうまく機能するか不安だったけど、できてるっぽい
- 実際にフォトンマッピングで使う場合は、球じゃなくて楕円体で絞り込んだり、法線があまりにも違ってたらはじくとかする必要があるかもしれない
- Proce55ing(Java)はどうも…
- ソートさせるときに軸によって条件を外部から与えたい、けど関数ポインタがない、のでファンクタを渡すようにする
- いちいちベースクラスを作って継承してオブジェクト生成して…とかメンドイ
- KDTreeクラスがPhotonクラスに依存、分離させたい
- ソートさせるときに軸によって条件を外部から与えたい、けど関数ポインタがない、のでファンクタを渡すようにする