くまりゅう日記

もっと過去の日記
[.NET | BeOS | Blender | COLLADA | fossil | mono | monotone | NPR | OpenGL | PeerCastStation | Riko | Ruby | Silverlight | TRPG | XNA | ゲーム | ゲーム作り | ]

2014-11-06

日記

全然片付かない……。

全然ってことはないんだけど、結構片付けたなーと見回してみると、まだまだやらなきゃいけないところが沢山あって間に合わないんじゃないかと不安になってくる。間に合わないことはないと思うんだが……。

[PeerCastStation] monoで上手く動かん続き

monoで何故だかCPUを食い潰してしまう問題の調査続き。

MonoDevelop(というかXamarinStudio)でデバッグしてると再現しないなぁとか思ってたけど、数日動かしたら再現した。再現したのだが……。結局ブレークできなかったわ。予想はしてたけど。

monoのデバッグってVMとデバッガが通信してやってるっぽいので、CPU食い潰してる(VMがなんかアレっぽい状態)だとデバッグできない可能性が高いんだよね。実際それにひっかかったようだ。 ブレークどころか停止もできなかったのでプロセス強制終了して後には何も残らず。いや、メッセージ出力があったか。monoの内部でmallocに失敗したとかなんとかのログを吐いていた。メモリが一杯だなんてことは全くなかったが何故だろう?これが引き金になったかどうかもわからない状態ではあるんだが。

ところでXamarinStudioで.NET4.5向けのビルドができないと思っていたが、見たら4.5.1向けのプロファイルを使ってたのが悪いらしくて4.5向けは普通に選べばビルドできた。その間XamarinStudioの更新を挟んでいるので、更新でできるようになっただけかもしれない。 4.5ならすぐ再現するのかと再度デバッグ開始してみたが、また数日動かしてるものの元気に動いてやがる。デバッグじゃだめなのか、それとも別な問題なんだろうか……。

書いてて思い付いたんだけど、PeerCastStationでは誰も捕捉しなかった例外をトラップして、落ちる前にログを吐くようにしてる。 もしかしてこれでログ吐こうとした時にまた例外投げて無限ループしてるんじゃないだろうか。 スタックオーバーフローしそうな気もするけど起きないかもしれないし。 この場合だとmonoがデバッグできない程に無限ループするというのも納得できる。 ちょっとこの方向で調べてみるか。

[Ruby][OpenGL] テッテレーション

なにがテッテレーションだよ馬鹿か!

そんなことよりテッセレーションしようとしたんですよ、テッセレーション。 文字の描画ができたのはいいけど、曲線の分割はCPUでやってるし、分割数は一定で面白みもないので、GPUテッセレーションしたいなと。最近のAtomはGL4.0サポートしてるのでHWテッセレーションできるみたいですよおそろしいですね。

OpenGL(Direct3Dはもちろん)のテッセレーションは全く触ったことなくて、なんだかとても難しそうだと思っていたんだが、理解できてみると全然難しくなかった。しかも強力だ。

テッセレータというんでプリミティブを分割する物だと思っていたし、さらに入力はいつものポリゴンじゃなくてパッチしか受け付けないというのでパッチってなんだよ激しく難しいよーと考えていたんだが、テッセレータはなんのことはない、単なるプリミティブジェネレータであった。

テッセレーション制御シェーダで何個頂点(というか辺)を生成しますかねってのを指定すると、テッセレータがプリミティブを生成しまくり、生成された頂点がテッセレーション評価シェーダに渡ってくるのであとは好きにしろって感じだった。生成された頂点間のつながりはisolinesかquadsかtrianglesかを前もって指定しておける。ほら簡単。

パッチ?入力した頂点はどこいった?この辺は実は関係なくて、テッセレーション制御シェーダの入力としててきとーに使っていいよーという感じだった。実際に生成されるプリミティブと関係なく好きなようにできるので、プリミティブの入力じゃなくてパッチってことになってるのね。

そこまで理解できたらあとはじゃあまあ適当にすればいいのねって感じで好きにやってやった。 ちょっと気になるのはテッセレーション制御シェーダが有効なら頂点シェーダいらなくねってのと、テッセレーション制御シェーダはパッチの制御点単位じゃなくてパッチ単位で実行してくれた方が嬉しいんだけど?ってあたりか。 テッセレーション評価シェーダのgl_inはパッチ単位で渡ってくるんだから、テッセレーション制御シェーダのgl_outもパッチ単位で渡した方が自然じゃないですかね?

とはいえ、最初からちゃんと理解できてたわけではないので、まずは曲線の分割をしてみた。

辺の分割をした結果

曲線を分割して線だけで書いた結果だ。 上が一律8分割、下が一律4分割、とかだっただろうか。 ちょっとコードが残ってないのでうろ覚えだが、まあそんな感じ。 とりあえず下の方がカクカクしてて、上手く動いてるようだ。やったー。

ここまで出来て一旦満足してたんだけど、塗りまでやるのが目標なのでもうちょい考えてみた。 当初は辺の分割まで出来たら、分割した辺を一辺とする三角形をジオメトリシェーダで生成するつもりだった。 しかし、テッセレータが単なるプリミティブ生成器だと分かった今となってはジオメトリシェーダはいらない子。 プリミティブの生成はテッセレータでやっちゃいましょう。 しかし分割するのは三角形の一辺だけで十分なんだけど、三角形生成するとやっぱり均等に分割なのかな?と思ったら辺ごとに分割数決定できた。こりゃ便利だ。

右の辺だけ4分割した三角形

試しにやってみた図が上のもの。右の辺だけ4分割できてることがわかる。中央の点いらないんだけど、辺毎に分割できるからこれは削れないし、まあそこまでケチる理由もない。これで十分。

あとは右の辺を曲線に対応させて、左下の頂点を文字の左下にひっぱればいいだけ。さくっと。

塗り潰しまでできた

曲線は一律で分割じゃなくて、だいたいの長さに応じて分割数が増えるようにした1。図だとだいたい8ピクセル毎に分割数が1増えてる……んじゃないかな。 まあ悪くはなさそうに見えるが、「え」のにょろんが出るあたりや、「お」の左下などカーブがきつい部分はちょっと厳しそうに見える。曲がり具合も加味してあげた方がいいか。

曲率の計算方法とか教えてもらって、長さよりは計算できそうだったが、曲率からどうやって分割数にすればいいかわからんし、そんなに厳密な計算もいらないな、曲がり具合さえ反映できればいいんだが。 しばらく考えてたりヒントを貰って、制御点で作る辺の角度を反映させればよさそうだとなった。じゃあそれはよくやるよね。2辺のベクトルを正規化して内積とればcosになる。同じ方向なら1.0、直角(90度)なら0.0になるから、適当な値かけて長さによる分割数に加味してやればいいだろう。とりあえず適当に6とか掛けて長さによる分割と足してやることにした。それが下の図。

角度も加味して分割数決めた

長さの方はだいたい16ピクセル毎に分割数増加にしておいた。頂点数数えてないんでわからないんだけど、見た感じは頂点数が特別増えた感じはないし、全体的になめらかになってくれた。「え」のにょろんが出るところなんかは細かく分割されてるが、上の棒なんかはちゃんと分割数少なめのままだ。よく見ると「あ」「お」の右下や「う」の下などなめらかなカーブがちょっと気になるところあるけど、そんなに気にするほどでもないし、もうちょい値の調整すればなんとかなりそうだしべつにいいか。

コードも上げようと思うんだけど、フォントがないとだめだったり、OpenTKのバグを手元で直したやつ使ってたり、フォント読み込みの部分が一番長かったりするので、一旦整理してから上げるようにします。

  1. 二次ベジエ曲線の長さを計算するのはすっごい大変そうだったのでいろいろ考えてみたところ、3つの制御点でできる三角形の辺の長さの合計÷2でちょっといい感じになった。近似と呼ぼうにもひどい計算だけど、分割数決める目安程度としては使えそうだったのでこれでいいや。 


ページのトップへ | トップ «前の日記(2014-10-30) 最新 次の日記(2014-11-10)» | 編集 | kumaryu.net by kumaryu