Artichoke Brethren

カリフォルニア・ベイエリアに住む CG エンジニアの気まぐれなブログ (ただいま引っ越し中)

2011年07月

さて少しコード整理してみます。

スプラインのベジェ変換は一度やればいい話なので、キャッシュしてしまいます。動的言語はこうした処理が泥縄にかけるんで楽ですね。後悔することも多いですが・・・

これだけでかなり軽くなりましたが、やはりちょっと大きなデータを読んだりすると、すぐにMacBookAirのファンが盛大に回り始めてしまいます。これはおそらく新型のCorei7なMBAを買ってこい、ということなのだと思いますが、もうちょっとどうにかしてみます。

Firebug のプロファイラがお手軽なので、これを使ってみましょう。

profile1.jpg

こんな結果になりました。createBezierPath は svg の path エレメントを作っているところ、apply は3D座標変換ですね。差し当たって vec4 を使う意味はあまりなかったので、vec3 をそのまま使うことにします。glMatrix のベクトルは typedarray なんですが、演算だけだと通常の float array とどっちが速いんでしょうね? よく調べていないんですが、後で webgl と混ぜたい気持ちもあるので typedarray に統一していくのが良さそうです。

パーサ側も直すのが面倒なので、キャッシュした結果だけ vec3 にしました。glMatrix、Cプログラマには取っ付きにくいインタフェースですが慣れると便利です。path エレメントの生成も毎回やる必要はなかったので、これも固定にしてしまいます。d アトリビュートの変更だけで再描画できるようになりました。empty() も毎回やらなくてよくなります。この方が自然ですよね。

そして今更気づきましたが、svg の座標系は左上が原点になるので GL 的には上下が逆でした。transform アトリビュートで反転しておきます。

grabcad で iges がいくつか拾えるので、もらってきて試してみます。円弧とトリムドサーフェスがないとまだまだちゃんと出ないです・・・

(現状のデモはこちら IGES to SVG converter )

iges_ss2.jpg

 
先日のバージョンはNURBSカーブをベジェ化して表示したまでだったので、次はサーフェスもやってみます。
カーブができていれば簡単で、パラメータUに関してベジェ化を行い、その結果をVに関してベジェ化することでBスプラインサーフェスはベジェサーフェスに変換できます。

ベジェ化部分を共用したいので、IGESパーサのスプラインを直接読むのではなくて一時的に別の構造を経由するようにしておきました。サーフェスでは同じノットベクトルで複数のスプラインを処理するので、その辺りができるようにしておきます。

さてサーフェスが表示できるようなったんですが、カーブならともかくサーフェスを2D表示してもちっとも面白くありませんでした。そこで無理矢理3D表示にしてしまおうと思います。本来は webgl を使うべきですが、Lion にアップデートしたら Chrome の webgl がうまく動かなくなってしまったので、今回は svg で 3D に挑戦してみます。

path エレメントを作る直前で、座標変換するようにしましょう。マトリックス操作は一から作ると大変なので、webgl でお世話になっている glMatrix ライブラリを使います。これ非常に簡単で良いです。

なかなかいい感じになってきました。動かすのはこちらから
IGES to SVG converter (firefox5, chrome12, safari5.1 で動作確認)

iges_ss1.jpg

今時の3Dビューワは画面のドラッグで視点操作ができないといけないので、カメラ制御用のオブジェクトを作りました。glMatrix の lookat 関数には GLU と同じように視点・注視点・アップベクタを渡せますので、これらを操作するような rotate, translate, dolly を作っておきます。

視点を操作したら、modelview 行列を更新します。今回は平行投影を使いますので projection はいりません。なぜか?それは svg で自力でニアクリップをするのが大変そうだから、です(実際のソースではパースも試したので identity で projection をかけてます)。

var modelView = mat4.create();
mat4.identity(modelView);
mat4.lookAt(eyeVec, refVec, upVec, modelView);

この modelView を頂点ごとにかけてやれば OK です。今回はさらに手抜きして、ビューポート変換を svg の transform でごまかして、頂点変換でスケールだけすることにします。svg の変換でもスケーリングは可能ですが、線の太さも変わってしまいます。線幅のスケーリングを回避する vector-effect: non-scaling-stroke というプロパティもあるんですが、chrome では対応しているものの firefox はまだみたいでした。

そんなわけで無事3D表示。ちょっと楽をして、制御点は座標変換してるんですが、その結果の2次元座標で svg path のスプライン描画しちゃってます。平行投影だとベジェがアフィン不変ということもあり、面白いですね。

描画の度にベジェ変換しているのでさぞ遅いだろうと思いましたが、結構いけるみたいです。chrome, safari, firefox では余裕でした。最近のjs環境すごいですね〜。絵が出せて楽しくなってきたので、次はちょっと効率を良くしてみます。

引っ越しで忙しかったけどようやく落ち着きました。

Lion にアップグレードしたら chrome で webgl が動かなくなってとても悲しい気持ちに。
なので SVG をやってみようかと思います。

canvas はほとんど GDI みたいな感じでひたすら自力で描画するものですが、SVG はチャート書きや静的なデータ描画に向いてますね。奇麗なので良いです。しかしこれも webgl と同様にデータの保護が難しいですね・・・

Illustrator などで作るのが一番良さそうですが、せっかくなので別の経路でデータを作ってみようということで、今回はIGES を読んでみることにしてみます。IGES は互換性が悪いことで有名な CAD 系の古いフォーマットですが、いろんなソフトが対応しているのでやりがいはありますね。日本語の解説が こちらのページ に詳しく、参考になります。規格書的なものは US product data association のサイトからダウンロードできるようです。

一目見てわかるように、テキスト形式で固定レコード長の非常に FORTRAN っぽいフォーマットです。実際文字列とか FORTRAN 式で書かれてますし。でもこういうテキスト処理は javascript が得意なので良さそうです。

規格書を見るとエンティティの種類が山盛りあって、主にこれが互換性の問題になっているようです。ポリゴンなんかはどうやって出すのが正しいのかさっぱりわかりません。変換行列とかも謎すぎないか? 今回は Maya からエクスポートしようと思うので、126 と 128 の NURBS だけ対応してみることにします。もちろん SVG は二次元なので、なんらかの方法で投影しないといけませんが、今回は xz 平面でやりましょう。

さてファイルのパースは割とすぐにできそうなものの、NURBS を SVG にするのはあんまり簡単ではないようです。SVG の path エレメントの仕様を見てみると、スプライン的なものは2次ベジェと3次ベジェがありますね。スプラインの世界は実はとてもディープで踏み込むと簡単には帰って来れないくらいなのですが、ざっくり言うとベジェは始点と終点でコントロールポイントを通過するもので、その間の制御用コントロールポイントが一つだと2次、二つだと3次、という感じですかね?

Maya でごく普通に作ったカーブは、3次の non-uniform b-spline になると思います。正直長年 Maya を使っていてカーブやサーフェスにウェイトをいれたことがありません。さてBスプラインとベジェは互換性があるので、比較的簡単に形状を保ったまま変換することが可能です。詳しいやり方はちゃんとした書籍を調べて頂きたいですが、多重ノットがあればコントロールポイントを通過するので、多重でないノットにノットを挿入してやれば良い、のです。たとえばコントロールポイント5個の3次Bスプラインのノットベクトルが
0 0 0 0 1 2 2 2 2
だったとすると、1 のノットを2つ足してやれば良いわけです。ノットベクトルにはただ挿入すれば良いですが、制御点の方はというと、そのノットが影響する区間に関していい感じに内挿すればよい、ということになっています。個人的には CAD CG技術者のためのNURBS早わかり という本が面白くて詳しくて好きでしたが、入手困難なようです。こちらのページにも詳しいアルゴリズムが書いてありますね。
ちなみに Maya の curveInfo ノードやAPIで得られるノットベクトルは最初と最後が省略されていますので気をつけましょう。詳しくは MFnNurbsCurve のマニュアルに載っています。

これをまともにやると非常に計算量が無駄なのですが、それでも多重ノットだけから構成されるスプラインに変換できて、それがつまりベジェになります。(ウェイトはまだ考慮してません)

というところまで作ってみました。まだ全然面白くないですけど。


ちなみに生成した SVG をダウンロードしたいと思ったのですが、dataURL を使ってみたもののどうしてもファイル名がうまくセットできなくて、結局 flash 利用のライブラリを使ってしまいました。でもこれ便利ですね。

↑このページのトップヘ