睡眠時の夢の描画処理について
注意:筆者は脳科学に詳しいわけではありません
ちょっと面白い夢を見たので朝に投稿。夢の中で見ている風景・映像は意識外の箇所も全て描画されているのだろうか?という疑問を持ちました。
どんな夢を見たか
場所は、おそらく図書館内部。主要な登場人物は僕以外に 2 人。なにか真剣な目で PC モニタを凝視している女性と、その対面に座って PC を操作している男性。双方、僕が見知らぬ人物です。女性は顔半分を覆うくらい大きなレンズの眼鏡をかけており、黒髪、黒い瞳。男性は、明るめの茶髪、茶色の瞳で眼鏡はなし。
上記を認識した状態で、女性はいったい真剣な目で何を見てるんだと思っていると、登場人物の 2 人が会話を始めました。
男性「……なにしてるの?」
女性「調べもの」
男性「いや、アニメ見てるでしょ」
女性「そんな事実はありません」
男性「眼鏡に反射してるから、バレバレだよ」
女性「あ、それは盲点だったわ」
この会話を聞いて、女性の眼鏡を見るとたしかに PC モニタの映像がレンズに反射していました。
が、おかしい。僕は女性が大きなレンズの眼鏡をかけていることと、瞳が黒いことは事前に見て確認していました。大きなレンズなので、映像が反射していればすぐに気がついたはずです。また、レンズに映像が反射していれば、瞳が黒いこともわかりにくかったはずです。なので、僕が見ていたときは映像がレンズに反射していなかったはずなのです。
おかしい、なぁんかおかしい。まるで僕が認識して初めて描画されたかのような……まるでゲームじゃないか、と考えてふと気がつきました。あ、これ夢だ、って。ここで目が覚めました。
所感
いやぁ、まるで 3D ゲームのようですね。見えないところ(認識外のところ)は処理が重くなるので基本的に描画しない的な意味で。まぁ夢の中の僕の目が節穴だった説もあるし、夢の処理が重いってなんだよって話ですが。夢の中で頭をフル回転させると目が覚めやすい印象があるので、夢を見ているときって実は頭はそんな働いていないのかな。だから夢の描画処理って手抜きされていたりするのかな?どうなんでしょうか。
VR ゲームってそのうちにこういう工夫もするんだろうなぁと思ったりも。脳波測定なり Eye tracking (日本語だと視線検知かな?)の技術を利用して注視している箇所を取得できれば、細かく描画する箇所、手抜きできる箇所とか判別できそうですし。
こういう面白い夢を見たのは久しぶりな気がします。ちなみに前に見た面白い夢は野菜が空を飛んでいる夢です。想像してみてください。人参やごぼうが鳥のように自由に空を飛ぶ姿を……シュールで忘れられません。
Windows の Vim あるいは Emacs 化計画
前回の続きで、UIAssistant でのキーバインド変更計画です。
本日のメニュー:Vim の f
,F
,t
,T
の機能を実現してみようと悪足掻きする内容となっております。
前書き
前回までは、モード変更によって各キーを入れ替える(j は ↓キー、k は ↑キーに入れ替えるみたいな)ことを考えていたのですが、他にも Keysnail のように組み込みコマンドを実行できたら便利だと思ったので、組込みコマンドを用意してみようと思います。そこで一旦 Vim や Emacs で便利な機能ってなにがあるかな?を考えてみました。Vim の f
,F
,t
,T
が便利だけど実現できるのかな?とふと思い、試してみることに。
その前に f
,F
,t
,T
について
知っている方は、次の見出しまで読み飛ばしてください。
f
は f*
で、キャレットの右側にある *
まで移動する機能です。;
で繰り返し移動ができます。
例えば、|
をキャレットとして、h|oge hoge
という文章があったとします。fg
と入力すると、hog|e hoge
とキャレットが g
の後ろに移動します。
ここで ;
を入力すると、再び fg
と同じ挙動をして、hoge hog|e
と次の g
の後ろに移動します。
t
は文字の手前に、F
, T
はそれぞれ f
, t
とは逆向きに左方向へキャレットが移動します。
試してみました
Oem1
はセミコロンのことです。fo
と To
で o
に移動します。
できました。が、あれです。問題多数。
問題
- 今のところ Win32API で作成されたアプリケーションじゃないと動かない(WinForms、WPF は駄目)
- WPF の場合、Windows Automation API で実現できそうだけど、WinForms は駄目っぽい(詳細な調査が必要)
- というか、WinForms は無理じゃね?(軽く試して絶望中)
- ぶっちゃけ、有用かどうか現段階ではよく分からない
後書き
諦めたい
UIAssistant 次回作(Vim, Emacs 的なサムシング)
Vim や Emacs と同じように、モード切り替えによるキーバインド変更が UIAssistant で実現できたら面白そうだと思いました。
UIAssistant についてはこちらを参照ください。
ためしてみました
ちょっと楽しい
今後について
今は用意されているモードしか使えませんが、もっと汎用性をもたせて、ユーザがモードを作成できたら夢が広がる気がします。ノーマルモードとインサートモードを切り替えるように、Dvorak 配列と QWERTY 配列を切り替えたり、QWERTYUIOP@[ がファンクションキー(F1-F12) になるようにしたりとか。ただ、設定画面が面倒なことになりそうです。
おわりに
文章がいつにもまして酷い。
2016/5/12 UIAssistant についてちょっと追記しました。
マルチスレッドでグローバルフックするときの注意
今日のキーワード:
SetWindowsHookEx
、WH_KEYBOARD_LL
(WH_MOUSE_LL
)- マルチスレッド
- グローバルフック
やりたいこと
メインの UI スレッドとは別スレッドでグローバルフックしたい。
例えば、描画の処理が重い場合、UI スレッドがそちらの処理で手間取り、キーボードやマウスの入力を処理できなくなる可能性があります。そういった場合、別スレッドでキーボード等での入力処理を取り扱いたくなります。
結論から
UI スレッド以外で、SetWindowsHookEx
を呼び出すときは注意が必要ですよ、というお話。
Why? なぜなのか
This hook is called in the context of the thread that installed it. The call is made by sending a message to the thread that installed the hook. Therefore, the thread that installed the hook must have a message loop.
LowLevelKeyboardProc callback function (Windows) より
低レベルキーボードフック (WH_KEYBOARD_LL
) を使用する場合、SetWindowsHookEx
を呼びだすスレッドは、メッセージループを持っていなきゃ駄目という記載が MSDN にあります。
これを忘れていて僕はドハマりしました……。SetWindowsHookEx
が失敗する?エラー?なんでだ?で数時間悩みました。
How? どうやって対処するのか
別スレッドにメッセージループを持たせて、別 UI スレッドにしちゃいましょう。C# (というか .NET系)の場合、以下のページが参考になります。
メッセージループをアプリケーション内で複数作ってみる - 亀岡的プログラマ日記
メッセージループを持つスレッドが複数ある状態になりますが、場合によっては効果的だと思います。先程の例であれば、描画に専念する UI スレッドと、入力に対する処理に専念する UI スレッドのように専業化し、そのメリット、デメリットを考えて、有効なら取り入れるという形ですかね。UIAssistant には取り入れて入力のレスポンスをよくする予定です。