wOCEではデカい領域を使えるので窓を見失うからと窓ナビゲーションを付けてみた。
拡大しないとわかりにくいかもだけど、黒っぽい円の内縁より外にある窓を光点として表示するようにした。円の外縁は無限遠なので全ての窓が表示される。今回はテキトーな窓を縦横32Kの範囲にランダムに20個作ってみた(最初は100個作るようにしてたんだけど撮影可能時間内に作り終えなかったので減らした)。
そして表示方法を変えてみたのがこれ。見てくれは変わってないけどこっちのほうがわかりやすい動かし方になってる。
wOCEではデカい領域を使えるので窓を見失うからと窓ナビゲーションを付けてみた。
拡大しないとわかりにくいかもだけど、黒っぽい円の内縁より外にある窓を光点として表示するようにした。円の外縁は無限遠なので全ての窓が表示される。今回はテキトーな窓を縦横32Kの範囲にランダムに20個作ってみた(最初は100個作るようにしてたんだけど撮影可能時間内に作り終えなかったので減らした)。
そして表示方法を変えてみたのがこれ。見てくれは変わってないけどこっちのほうがわかりやすい動かし方になってる。
チケットの親子関係を作れないのがどうにも不満なのでプロジェクトの管理をbitbucketのプロジェクトページから自前鯖で立てたRedmineのページへ引っ越した。
が、もしかすると、というかRedmineが外部のリポジトリを使えるとするとリポジトリは移さないほうが良かったかも知れぬ。
実は前回は解けてなかったわけだが、誤差を求めるように方針を変えたらあっさり解けた。DoEは磁化分を直接求めてるので誤差でなく直接計算しようとすると四点のデータが必要なのかも知れん。
VRHMD座標系、mを磁化値、eを回転前の地磁気、M0を回転前の観測値、M1を回転後の観測値、Pを(逆)回転、QをPの共役、M0を回転させたM1の予測値をMr=PM0Q、いずれも四元数形式とすると、
M1 - PM0Q = m + PeQ - P(m + e)Q = m - PmQとなり、あとは各軸に分けて三元方程式を解くだけなのでもう解けたも同然なのだが...四元数による回転を含む三元方程式を数値ではなく文字で解くのはかなーりめんどくさいのぅ。
wOCEでは今のところサーバ側で描画して画面へ転送という処理にしているが、これを画面側でも描画できるようにしたくて最初は画面側のプロセスで描画しようと思っていたけど共有メモリを確保して別プロセスでやるほうがよさそうだ。
画面側の処理は時間に煩いけど描画処理は時間が読めないのでプリエンプトできないと処理が回らんし、画面専用機をシングルコアで使うとコアが余ってしまう。
てーことで、画面側は画面側描画指定CanvasWidgetは共有メモリと描画用プロセスを持ってて描画コマンドは描画用プロセスへ回す。GC消滅コマンドで描画用プロセスはアップデートコマンドを範囲と共に送ってくるので共有メモリからテクスチャへ転送...updateCanvasコマンドは共有メモリも描いてからテクスチャへ転送...。てなところか。
これで画面側描画であろうとなかろうと同じ使い方ができるというもの。
だいたいは動くけど
マルチスレッド描画はフレーム非同期コマンド蓄積へのステップだったのでこれはかなーり残念な結果であるとともにテクスチャのアップデートまでフレーム同期でやらにゃならんということでもある。
テクスチャアップデートだけフレーム同期としてもいいわけだが。
Oculus純正のコードでRiftを動かしたあとだと送ってくるパケットが雑になるのだけれど、これをどうにかできないものかとまずは何が起きているのか調査してた。とりあえず設定値を取得して比べてみることに...
distortion_k: 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000
eye_to_screen_distance: 39620, 39620
lens_separation: 63500
vertical center: 30840
screen size: 119340 x 66300
resolution: 2160 x 1200
distortion_type: 1
command id: 0
display info:56
keep alive interval: 3
packet interval: 59392
sensor coordinates: 0
motion command keep alive: 1
motion keep alive: 0
auto calibration: 0
use calibration: 0
calibration test: 0
raw mode: 0
flags: 20
command id: 0
sensor config
getconfig returns:7
mag scale:1300
rotate scale:2000
accel scale:4
getscale returns:8
distortion_k: 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000
eye_to_screen_distance: 39620, 39620
lens_separation: 63500
vertical center: 30840
screen size: 119340 x 66300
resolution: 2160 x 1200
distortion_type: 1
command id: 0
display info:56
keep alive interval: 3
packet interval: 59411
sensor coordinates: 0
motion command keep alive: 1
motion keep alive: 0
auto calibration: 0
use calibration: 0
calibration test: 0
raw mode: 0
flags: 20
command id: 0
sensor config:7
mag scale:1300
rotate scale:2000
accel scale:4
sensor scale:8
ログ順の関係で上が新しいので逆に読む。で、見ると異なるのはsensor config/packet intervalだけで、デフォルトが59392、雑データの時が59411になる。これは16進だとE800とE813になる。雑データはゲインが1/10になっているのかと思っていたがデータの名前から考えてΔtが10倍になっているようだ。まぁRiftの姿勢取得は2ms間隔と結構煩いので使ってない時は頻度を落とすとかしているんだろう。
おそらくこれは何らかのカウンタの値で上位を変えるとどうしようもない状態になるっぽい。もともとデフォルト値を設定することが目的なのでそこは深く考えないことにする。考えたところで誰かが勝手に決めた仕様に過ぎないし。
それにしてもdistortion_kに値が入ってないとか...これは光学系の歪み補正パラメタで、最初の3つは自乗項、四乗項、六乗項、あとの3つはRGBそれぞれの色収差補正値が入っているべきだったものだ。
ともかく、sensor configを取得してpacket intervalがデフォルトでなかったらデフォルト値にして設定すればおkってとこなのでそのように組むとしよう。
なので実装して3Dオブジェクトを取り込めるようにするためにはデータが必要で、別のツールで作ったデータを取り込む必要があるので変換するツールが必要で、そもそも取り込むためのデータが必要で...と動かせるまでが結構長くて困る。
今後の方向から言えば、一度ゲーム系の機能から離れて窓系機能に戻ろうかと。ちょっとシステムまるごと握ってないと実現が難しそうな(Xだと窓マネージャでできるけど)新しいUIを思いついたので。
時間が空いたが動画を取得したので貼ってみる。動かしてるのはwOCE用のサンプルアプリで画像ビューア。無難なの...と選んだ結果「オフィスに貼ってあるアレ」的なフォルダの中身を表示させてみた。
また動画の終わりのあたりでマウスカーソルを動かして奥行きをデモしたりしてる。
なんて思ってたんだが実はテクスチャの更新が遅いのは更新回数が原因だった。
どうやらテクスチャの更新は思ってた以上に回数依存ぽくて、一度に更新するサイズを拡大したらメインスレッドでの更新でPBOも使ってないにもかかわらず一発で十分なほど改善された。
これだとスレッド化してPBOで更新するようにすれば大きめのテクスチャをまるごとでも更新できそうなんだけど、それをすると通信路が詰まりそうなので今の方法で問題が出るまで放置することにする。てかおそらく今でもリモートで動かすと詰まりそうだし。
「キャスト」というのは違うかも知れん。画面を動画でキャプチャする機能を復活した。
今回はPBOを大量に用意してフルフレームで「ぬるんぬるん」キャプチャできる上に通常動作への影響が感じられないくらいの低負荷にできた。
最初はPBOではなくテクスチャに格納するようにしていたのだが、テクスチャからメインメモリに読めるはずのglGetTextureが全く機能せず画像が真っ黒になってしまうのでPBOを使ってみたのだが、画像の取り出しも高速化されているハズで満足な結果になった。
しかし、動作確認に使ったサンプル画像がアレなので動画の公開はまた今度〜(ぉ
引っ越し先。 見えるかな。