厳密な光線追跡 - その13 [光線追跡エンジンを作る]
うわ、続いてる。僕にしては快挙。スタック深さ2を超えた。
まあ、それはいいとして、Mathematicaに書いた光線追跡エンジンはとっくに動いてるんだけど、ここで公開するのにはためらいがあった。なぜかというと、コードがあまりきれいではないのと、非球面の光線追跡がとんでもなく遅い、というのが原因。
なんで非球面の追跡が遅いか、というと光線が一本与えられるたびに非球面係数から具体的な非球面式を作ってそれからその微係数も作って、ということをしているせい。当然、係数が与えられたらその具体的な式はどこかに保存しておいて、追跡の時はそれを参照すれば速くなる。しかしそのためには係数の組と式とをまとめて保存するしくみが必要。しかしMathematicaを使う時は、式は複雑になるけど独立した要素はそれほど多くないのが普通で、今回のように考慮しなければいけない要素が増えてくるとMathematicaでもちゃんとオブジェクト設計をしないといけない。それを怠って前回書いた式をそのままMathematicaで評価するようなコードを書いていた。
Mathematicaでも独立した要素が多い場合、オブジェクト指向な考え方を使った書き方をすべきである。ということで、全部チャラにして書き直すことにする。まず、光線追跡エンジンのためにはどういう風にオブジェクトを考えればいいか、ということから始める。
すべての面は、式のまとめに従って
グローバル座標では光軸をz軸に限定しない。コーディング上ではそれを前提にしないように気をつけることにする。
やはり面と媒質はそれぞれ独立なオブジェクトとしたほうが扱いは楽になる。
また、面間隔も面の属性ではなく、面を配置するオブジェクトが持つようにした方が面オブジェクトは簡単になる。したがって「面間隔」で配置するのではなく座標の絶対値で配置するのが簡単になる(ユーザインターフェイスとしては「面間隔」でもいい。内部で変換すればいいだけである)。
つまり、
面オブジェクトは自分が座標原点にいるとして光線との交点と屈折角を計算するので、光学系オブジェクトが面に光線を渡すときに逆向きにオフセットや傾きを光線の方に与えてから渡し、屈折後の光線をもとに戻るようにオフセットと傾きを与え直してやる。これはかなりのオーバーヘッドになるけど、面オブジェクトが簡単になるのと、面の姿勢を気にせずにすむということは以前説明した。
まあ、それはいいとして、Mathematicaに書いた光線追跡エンジンはとっくに動いてるんだけど、ここで公開するのにはためらいがあった。なぜかというと、コードがあまりきれいではないのと、非球面の光線追跡がとんでもなく遅い、というのが原因。
なんで非球面の追跡が遅いか、というと光線が一本与えられるたびに非球面係数から具体的な非球面式を作ってそれからその微係数も作って、ということをしているせい。当然、係数が与えられたらその具体的な式はどこかに保存しておいて、追跡の時はそれを参照すれば速くなる。しかしそのためには係数の組と式とをまとめて保存するしくみが必要。しかしMathematicaを使う時は、式は複雑になるけど独立した要素はそれほど多くないのが普通で、今回のように考慮しなければいけない要素が増えてくるとMathematicaでもちゃんとオブジェクト設計をしないといけない。それを怠って前回書いた式をそのままMathematicaで評価するようなコードを書いていた。
Mathematicaでも独立した要素が多い場合、オブジェクト指向な考え方を使った書き方をすべきである。ということで、全部チャラにして書き直すことにする。まず、光線追跡エンジンのためにはどういう風にオブジェクトを考えればいいか、ということから始める。
4.1 座標系について
まず座標系を決めておく。とりあえずz軸方向を光軸と考える。すべての面は、式のまとめに従って
- 固有の局所座標を持つ
- 局所座標では、面は
- 原点を通る
- 原点での法線はz軸と平行
グローバル座標では光軸をz軸に限定しない。コーディング上ではそれを前提にしないように気をつけることにする。
4.2 オブジェクト設計
CodeVなどの汎用光学設計ソフトでは面の属性として- 曲率
- 面の次の媒質の屈折率
- 次の面までの距離(面間隔)
やはり面と媒質はそれぞれ独立なオブジェクトとしたほうが扱いは楽になる。
また、面間隔も面の属性ではなく、面を配置するオブジェクトが持つようにした方が面オブジェクトは簡単になる。したがって「面間隔」で配置するのではなく座標の絶対値で配置するのが簡単になる(ユーザインターフェイスとしては「面間隔」でもいい。内部で変換すればいいだけである)。
つまり、
- 光学系オブジェクトが、面とその間の媒質を保持する
- 面オブジェクトは面形状を保持する
- 媒質オブジェクトは屈折率を保持する
- 光線オブジェクトはその始点と方向、波長や強度などの属性を保持する
4.2.1 光学系オブジェクト
光学系全体を保持するオブジェクトを用意する。これは媒質0 面1 媒質1 面2 媒質2 ... 媒質n 像面(バッフル)というふうに順番と、それぞれの面の位置を保持する。
面オブジェクトは自分が座標原点にいるとして光線との交点と屈折角を計算するので、光学系オブジェクトが面に光線を渡すときに逆向きにオフセットや傾きを光線の方に与えてから渡し、屈折後の光線をもとに戻るようにオフセットと傾きを与え直してやる。これはかなりのオーバーヘッドになるけど、面オブジェクトが簡単になるのと、面の姿勢を気にせずにすむということは以前説明した。
2012-11-13 21:54
nice!(0)
コメント(2)
トラックバック(0)
とても興味があるあたりの話題で、すごく楽しみにしています。似たようなことをしたかったりすることもあり、非常に参考になります。また、「なんちゃってMathematica」も(いつか続編が来るはずと)あきらめずに期待してます。
by jun hirabayashi (2012-11-17 13:53)
コメントありがとうございます。
興味を持っていると伺うと恐縮です。うれしくなってもう少しがんばってやろう、と言う気になります。
「なんちゃってMathematica」も、最初は評価エンジンをyaccとlexでやろうと思ってたのですが、実は思うところがあってじかに書こうと考えています。気持ちが盛り上がったら再開しますので、長い目で見てやって下さい。
by decafish (2012-11-17 18:07)