!!!独り言日記 !!続・Shade8でのOpenGL on dialog_interface(2006/01/27) メモ書きです。 OSXで、以下のVer0.02はOpenGLのウィンドウをCreateNewWindowで生成して 管理してますが、HIViewのイメージから「HIViewGetWindow」を使って WindowRefを取得してOpenGL領域を割り当てる、とすると もっときれいにいけそうな気がしてきました。 また、時間のあるときにバージョンアップしてみます。 参考資料へのリンクです。 http://developer.apple.com/documentation/Carbon/Reference/HIViewReference/HIViewReference.pdf !!Shade8でのOpenGL on dialog_interface(2006/01/26) [[dialog_interfaceでのOpenGL描画|dialog_opengl_shade8sdk]]を 更新しました。 OSX版のソースとサンプルプラグインをアップしてます。 かなり強引なやり方ですが、それを分かっていただければ幸いです(^_^;;。 また、Windowsのほうも少し修正を加えましたので、 Ver0.02として再度ソースの更新をかけるようにしてください (関数・引数は変わりはありません)。 解説書く前に力尽きましたので、詳しいことはまた後で。 OSXでは、マウスイベントの取り方は強引です。 先日の日記での追加事項ですが、モーダルダイアログの脇から マウス処理をGetするために、タイマーイベントでマウスを監視して そこからマウスイベントを作るようにしてます。 !!不可能を可能に(2006/01/25) 大それたタイトルですが(^_^;;。 ほんと、これは不可能に近いことをしていたりします。 {{ref_image shade8_opengl_mac_20060125.jpg}} まず、Shade8(OSX)のダイアログ(dialog_interface)を細かくチェックしたのですが、 *WindowRefが階層を作っているわけではなさげ *ControlRefでコントロールが配置されているわけではなさげ *HIViewで階層を作っているわけではなさげ(ルートのHIViewはあるのですが、、、) で、じゃあdialog_interface上のwindow_interfaceでは どのようにコントロールを配置してるんだ?というのは 結局探れませんでした。 ダイアログが1つのWindowRef(実際はNSWindow)を持つ、 これを検出というところまでは、 Cocoaからのチェックで分かりましたが。 ShadeというよりもMacOSX自身のダイアログのイベントループを 奪うこと自体がかなり無理っぽいことのように感じてます。 後は、Cocoaとの関係ですね。Cocoaで生成したウィンドウ(NSWindow)は CarbonからはFrontWindow/FindWindowでゲットできないという問題です。 残念ながら、Cocoaからのアプローチでも 上記3つ(ルート以下の子のウィンドウまたはコントロールを取得)は取れませんでした。 これに加えて、マウス・キーボードのイベントを「モーダルダイアログでは」 横取りできなかった、これも大きいです。 (ダイアログのループは、すでにdialog_interfaceのがありますので、 これに並列して独自のスレッドでまわしてちょっかい出してみたのですが 描画以外のイベントがゲットできませんでした) しかし、上の画像ではこれを無理からに実現してます(OpenGLウィンドウの 配置位置だけ、制限があります)。 タイマーでティーポットが回転もしてます。 マウス・キーボードの横取りもOKです。 ダイアログの背景は灰色で変わってしまっているのは、Shadeのバグっぽいです。 と、もう少しで、Winと同様にOpenGL on dialog_interfaceが完成しますので、 また出来次第解説しますね。 ・・・私からの提案として・・・・ OSXで凝ったことをしようと思うなら、dialog_interfaceは止めて 独自にWindowRefを「CreateNewWindow」して「RunAppModalLoopForWindow」で ぶん回したほうがいい、とそう感じます。 さんざん掘っておいてなんなんですが(^_^;;。 OSXでアプリを作ること自体は(資料が少ない、API自身にバグがあるというのを 除いて)そう難しくはないのですが、イベント横取りはWindowsよりも 厳しいですね。 あ、それとOSX 10.4.4で確認してますが、スレッド周りは初期の 10.0や10.1時代と比べてかなり安定してます。 変なこと(特にメモリリークと描画などのバッティング)を しない限りは落ちませんね。 横取りが必要な場合は、これは例えばShade本体でOS依存の APIにアクセスできる仕組みを 実装してあげるほうがスマートである気もします。 う〜ん、でもOSX版のShadeでは 本体CocoaでプラグインがCarbonなので、 このあたりはOS自身(の橋渡し)がしっかりしないと難しいところではありますね。 ・・・ところで、OSXではJavaもネイティブ実装でしたよね、 どこまで使いものになるもんなのだろう・・・。 !!Objective-C++(2006/01/18) OSXのCarbonからCocoaの機能を呼び出す場合、1つのソースファイル内に C言語(またはC++)とObjectiveCが混在することになります。 このような言語体系を「ObjectiveC++」と呼ぶらしいです。 これ、ずっとつまずいていたのですがファイル拡張子が大事です。 リンクするファイルがすべてC言語(*.c)の場合は、cocoa(ObjectiveC)の記載する ファイルの拡張子は「'''m'''」でOKです。 Appleのサンプルである「CocoaInCarbon」も、C言語+ObjectiveCの組み合わせ。 このサンプル、Cocoa - Carbonの例として、かなり簡単に書いてありわかりやすかったです。 http://developer.apple.com/samplecode/CocoaInCarbon/CocoaInCarbon.html ところが、 1つでも他のソースファイル にてC++が混じっていると(*.cpp)、 ObjectiveCのソースファイル拡張子を「'''mm'''」としないといけません。 でないと、ビルドの最終段階のリンク時に「undefined symbols」が出たり、 ビルドは通っても実行した後にCocoaを呼ぶC関数にアクセスすると落ちたり、と 不安定になってしまいます。 いやはや、これを発見するまで1日費やしてしまいました。 またOSかコンパイラのバグかと思ってしまいましたよ(汗)。 で、ついにやりました!! ヤマカンがあたったようです。OSX版のShade8はメインウィンドウとモーダルダイアログは Cocoaで書かれており、上記のように「Carbon ==> Cocoa」の呼び出しで Cocoaから管理しているウィンドウをたどることで目的のウィンドウ(モーダルダイアログ) をゲットできました。 つまり「Carbonで生成されたウィンドウはCarbonAPIのFrontWindowで取得できるけど、 Cocoaで生成されたウィンドウは取得できない(同一プロセス内であっても)。この場合は、CocoaからNSWindowを取得して WindowRefに変換してCarbonに返してあげるとよい」の理論は正しかったことになります。 おかげさまで、MacでのShade/dialog_interface上のOpenGL描画は無事完成しそうです。 数週間悩んだ甲斐があったというもの。 Cocoaでは、以下の要領でCarbonで言う「FrontWindow」による最前面ウィンドウが ゲットできました。 NSArray *ar; NSWindow *win; int cou; WindowRef winRef; ar = [NSApp orderedWindows]; // 管理しているウィンドウの配列を取得 cou = [ar count]; // 配列内のウィンドウ数を取得 win = [ar objectAtIndex:0]; // オブジェクトの取得(0番目のNSWindowを取得) winRef = (WindowRef)[win windowRef]; // NSWindowをWindowRefに変換 ちなみに、Shadeでモーダルダイアログを出してから上記のCocoaルーチンを 呼ぶと、NSArrayの0番目はダイアログのウィンドウ、1番目は 大元のメインウィンドウ(図形ウィンドウがある一番大きなドキュメントウィンドウ) が返ってきてました。 フローティングウィンドウはゲットできてませんでした。 ということは逆もしかりで、「Carbonで生成したウィンドウは、Cocoaからは検出できない」ってことなのかな。 OSXの場合は、Carbon/Cocoa両方使えないと他のアプリを乗っ取ったりというのは 完全にはいかない感じですね。 !!追記(2006/01/17) OSXプログラムにて追記です。 「/アプリケーション/ユーティリティ/アクティビティモニタ」で プロセス一覧からスレッド詳細までもっと分かりやすく見ることができました。 後、ShadeプラグインからモーダルダイアログのWindowRefが検出できない問題に 加えてもう1つやっかいなことが。 CarbonAPIのCopyWindowTitleAsCFString(旧GetWTitle)で、WindowRef のウィンドウタイトルが取得できるのですが、これが WindowRefがゲットできている Shadeフローティングウィンドウの場合でも取得できてません(Shadeプラグインでの 話です。独自のCarbonだけのアプリでは問題なく取得できてます)。 で、いろいろ調べてみた結果、SDLでも同様な現象が起こるようで (OSX版のSDLはCocoaでコーディングされてます)、 「CarbonからCocoaのNSWindowの情報がうまいこと取れない」が 現実味を帯びてきた予感。 どちらかというと、OS自身の問題でしょうかねぇ。 ここまで、原因を時間をかけて絞り込んできたわけですが、最後の 切り札として「Cocoaでフロントウィンドウを取得してCarbonに渡す」 が残りました。 ということで、Cocoaの勉強もするかぁ。 幸い、OSXではCocoa/Carbonの情報交換は1つの実行ファイル(プラグイン) でも混在して行うことができます。 ツギハギゆえの不都合ですが、ツギハギゆえに助かるかもしれない、 といったところ。 さらっと見た感じでは、Cocoaのほうがソースが短くて すみそうですね。しかし、構文が独特なのでまずは理解から 始めないと。 ・・・文章を見返してみましたが、Carbon/Cocoa/NSWindow/WindowRef/SDLとか・・・ 知らない人から見ると暗号ですな(^_^;;。 !!OS XのNSWindow/WindowRef(2006/01/17) OSXでのShadeの挙動を深く探ってみます。 プロセス名は「xshade」、初期状態のスレッドは6つです。 Shade自身のスレッドを監視したところ、根本は「NSApplicationMain」から 始まっており、Cocoaで作られていることがわかります。 モーダルダイアログ(dialog_interface)のウィンドウハンドル(WindowRef)が 「FrontWindow/FrontNonFloatingWindow」で取得できないので、一週間以上 いろいろと調査しているのですが、モーダルダイアログ自身はCocoaのNSWindowから生成しているのではないかと推測してます。 テスト的に作ったアプリでは、モーダルダイアログのWindowRefも外部スレッドから 検出できるんですよね。 しかし、Shadeのモーダルダイアログは検出できず。また、メインウィンドウも検出 できません(フローティングウィンドウは検出できます)。 Cocoaはプログラム方法が分からないのでタッチできないのですが、 たしか昔のShade(Shade6くらい)では、メインウィンドウ・ダイアログ共に WindowRefが検出できていた記憶があります。 で、Shadeはモーダルダイアログを表示するときに1つスレッドを生成するようです。 これは1度生成したらShadeを終了させるまで保持するみたい。 また、メインスレッドでは「-[NSApplication runModalForWindow:]」でモーダルの イベントループをCocoaで発生させてます。 総合的な検証では、「Cocoaで生成したウィンドウ(NSWindow)は、Carbonの FrontWindow/FrontNonFloatingWindowで取得できないのではないか」という 疑惑が。 う〜む、NSWindowあたりを取得するAPIがCarbonにないものか・・・。 この上記のような調査は、当然Shadeの中の人でないとソースは入手できないため 探ることができないと思ってしまわれがちです。 ただ、いわゆるWindowsで言うSpyツールのような感じで、スレッドの挙動を監視することは実は可能です(ウィンドウの階層を見るのがないかなぁ)。 OS Xに開発ツールをインストールしたときにできるDeveloperフォルダ内の「Applications/Perfomance Tools/Thread Viewer」を起動します。 これでプロセス(起動しているアプリ)を選択するウィンドウが出るので、 対象プロセスを選択します。 これで、スレッドごとの情報が表示されます。 ・・・window_interface/dialog_interfaceで使うネイティブなWindowRef(Windowsの場合はHWND)を返してくれる関数を1つ追加してもらうと万事解決すると思うのですが(^_^;;。 回りくどいです(苦笑)。 OpenGL on ダイアログまでの道は険しそうですね。 !!WindowRefの階層化(2006/01/12) OSXでウィンドウを作る場合はCreateNewWindowを使うのですが、 この引数には親ウィンドウの指定がありません。 ウィンドウの上にウィンドウ描画領域を設けたいのですが・・・。 で、さんざん探して見つけました、「SetWindowGroup」でどうやら階層化できるようです。 しかし・・・分かりにくい・・・・。 WindowGroupRef gr; ... CreateWindowGroup(kWindowGroupAttrMoveTogether | kWindowGroupAttrSharedActivation | kWindowGroupAttrHideOnCollapse, &gr); SetWindowGroup(win1, gr); // 親のグループを登録 SetWindowGroup(win2, gr); // 子のグループを登録 のようにすると、WindowRefであらわされるウィンドウwin1にwin2が関連付けられます。 win1のウィンドウを動かすとwin2はそれについてきて、無事ウィンドウに ウィンドウを割り当てる、ということができます。 win2表示時に下に影ができるのですが、これはCreateNewWindowの第二引数で kWindowNoShadowAttributeを指定することにより影ナシにできます。 これ、何をしているのかというと、ShadeのダイアログでOpenGL描画を 行う実装です。この場合、ダイアログのウィンドウの上にOpenGL用のウィンドウを 乗っける必要があります。 しかし、まだまだ壁があって、Shadeのモーダルダイアログは なぜかウィンドウハンドル(WindowRef)をゲットできない。 う〜ん、フローティングウィンドウではゲットできるんだけどなぁ・・・。 !!Qcam(2006/01/09) 急に思い立って実験してみたいことがあったので、Logitechの 「Qcam for Notebooks Deluxe」というUSBカメラを買ってきました。 http://www.logitech.com/index.cfm/products/details/JP/JA,CRID=2204,CONTENTID=10168 ソフマップでポイント使って2000円代、安い買い物です。 プログラマとしては付属ツールなんてただのパセリ、プログラムで いじれないと意味がないということで制御できるか調査。 Windowsでは、DirectShowにてカメラのキャプチャ関連は制御できます。 現在、DirectShowはPlatformSDKに移行しちゃってるんですね。 必死でDirectX9SDKからinclude/libを探してました(^_^;;。 DirectShowの機能を使うと、1フレームごとの画像をRGBで ゲットできます。これができるといろいろ研究に使えそうです。 たとえば、動いている物体のみを除去したり、動きをモーションキャプチャしたり、ASIMO風視覚センサーを作ったり・・・。 手始めの実験として、セピア調フィルタをかけてみました(プログラムで制御してます)。上半分は普通の色、下半分はセピア変換してます。 {{ref_image qcam_20060108.jpg}} リアルタイムにかけることができるので、昭和風な雰囲気をカメラ 動かしながら出せて楽しいです。 いまやUSBカメラは安価で手に入りますし、最大120万画素まで 表現することもできるようになりました。 大学や余裕のある企業などで、この手の研究が流行ると面白いなぁと 思うのですが、いかがでしょうか。 !!MacでのOpenGL(2006/01/07) CarbonでOpenGL描画を扱うアプリ(ツール)を作るのは すごく簡単です。 [[ここ|Mac(Xcode)]]に実験ソースを置いておきます(Shadeとは関係ないよ)。 「AGL」というのを使うとOpenGL描画領域をアタッチできます。 後は、glXXXのおなじみのOpenGL APIを並べるだけ。 また、GLUTもOS XではOSに内包されてますので、 これもすぐに使えます。 で、Shadeで処理を奪う(独自OpenGL描画領域を実現する)には、、、 それ以前の問題で対象の親のWindowRefをゲットするのが難問です。 WindowRefの親子関係を取得するAPIはCarbonにないものかな・・・。Cocoaでは あるみたいですが。 !!Shade8 プラグインSDK - dialog_interfaceのOpenGL(2006/01/05) [[dialog_interfaceでのOpenGL描画|dialog_opengl_shade8sdk]]を 行うソース一式をアップしました。リンクよりソースとサンプルソース・ サンプルプラグイン(DLL)をダウンロードできます。 一応アルファ版ということで。 解説はまだ・Mac対応もまだですが、sample01.cpp 〜 sample04.cppを 見ると、なんとなく使い方は分かるかなと思いたいです(^_^;;。 解説は後で細かくいれます。 ちなみにサンプルソースである sample01.cpp 〜 sample04.cppは、Macでも実装は変わらない ように設計しています(そのままMacに持っていけばコンパイルがとおる予定)。 「opengl_window_class」というOpenGL描画を扱うクラスを 新設してプラグインSDKを拡張しています。 opengl_window_class関連のファイル(dialogopengl.cpp/openglwindowinterface.cpp/oglKeyboard.cpp/oglMouse.cpp)は見なくても問題なしです。 が、これを実装するために水面下でえらいことをしないといけない、 というのが理解されればしめたもの(苦笑)。 Shade上のモーダルダイアログでまともにOpenGLを使おうと思うと、 こんだけの処理・苦労をしないといけません。 私はオーバーライドの仕様はあまり好きではないのですが、ShadeプラグインSDKに あわせるためにあえてこんな実装にしてます(私はコールバック関数を アタッチするほうが好きなもんで)。 ドラッグ処理はこっち(opengl_window_class)の ほうが分かりやすいかなと思ってますが、どうでしょうか。 それと、仕様はもうこれで固まってますので 自作プラグインに実装されてもOKです。 残すはMacへの移植とAPIの説明を書きますね。 しかし、 dialog_interfaceの上にwindow_interfaceをマッピングする、 これ自体が付け刃的でかつ複雑かなぁという気がします。 これもラップはできるのですが・・・面倒なのでパスします(^_^;;。 !!Shade8 プラグインSDK - window_interfaceのkey_down(2006/01/05) 予想通りというか、ダイアログ内に配置するwindowinterfaceでの「window_interface::key_down」は呼ばれてませんねぇ。 Windowsではキーボードフックすることで対応できるのですが、 Macではできるだろうか・・・。 Win版でのdialog_interfaceのOpenGL描画は実装完了。 先にこっちのソースとサンプルを公開することにします(もうちょっとお待ちを、 解説やソースダウンロードはTipsのページの方に移行します)。 しかし、Shadeを使っていると図形ウィンドウやフローティングウィンドウ上の ちらつきが目につきます。 原因は何なのだろう・・・、これが重い現象に関連しているような気配もしますが・・。 !!e-ラーニング(2006/01/05) 東京帰ってきました。 親にパソコンの使い方を教えていたのですが、一日かけて使い方教えたところ 早速いろいろネットで検索してプリントアウトしてました。 実家も私と同じso-netなのですが、マニュアルもより初心者向けで簡単になっていますね。 ただ、正直なところso-net提供の初心者向けのマニュアルや簡単設定のCDはまったく 使いませんでした。 ほんとにキーボードに初めて触る、という人から見るとまだまだ 使える側(教える側)が意識を変えないといけないなぁと痛感しました。 まず、マニュアルといえども10ページ以上ほどあると読む気をなくしてしまいます(どんな簡単なことが書いてあっても)。 2ページくらいにまとめたクイックリファレンスがあればいいかなと (これは、パソコンの電源を入れるところからネットにつなぐまで)。 で、初心者さんのやりたいことは(おそらく)「ネットでの検索を使った インターネット体験」「メールでのやりとり」が先に来るかと思います。 というよりも、何ができるかからの模索、といったところでしょうか。 これにしぼると、各2ページもあればそれぞれを解説できるんでないかなぁ。 後、私も注意しなければならないのですが「うんちく」的なわき道にそれた 解説は、これは注意をそらすかもしれない、と感じます。 目標まで簡潔に一直線に説明するのが分かりやすい方法論かも。 後、難儀していたのが「ローマ字による全角漢字入力」。 親曰く、タイプライターとは違うね、ってことなので(私が逆にタイプライターを知らない(^_^;;)団塊世代以上の方には関門の1つかもしれません。 それと、マニュアルでは無理だと思いますが 動画でキーボード操作・ネット接続の操作を見せる、これも大事かも。 パソコン上でとなると(たとえばFlashで)、そこにたどり着くまでが 大変なので、紙の上で動画を見せることができるなんてあると 一番ベストかな(ビデオだと、今度はデッキの使い方説明がいるもんで、やはり距離ができてしまう)。がんばれ、技術革新(笑)。 年寄りだからITにはついてこれない、ってわけじゃなく 教え方の問題もいろいろあるんでないかなぁ、というのが私の感想です。 親の友人(もう軽く60歳超えてる)の方々は、普通にネット検索も メールも使いこなしているそうな。 時代ですねぇ。 !!あけましておめでとうございます(2006/01/02) 今年もよろしくお願いいたします。 今年の目標はまだ立ててないのですが、何か形に残すことができればいいなぁと。 とりあえずはMayaを使いこなせるようになりたい、と アプリケーション(ツール)を完成させたいですね。 仕事のほうは早く基盤(環境)づくりを安定させることができるように。 元旦に初詣に行ってきました。 運動がてら計15駅分くらい歩きました(^_^;;。 伏見から京都駅近辺+大阪御堂筋梅田からあびこまで。さすがに筋肉痛キました。 同じく一緒に行った友人も筋肉痛ということで 元旦からやりすぎ感がありますが、今年も気合入れていこうと 思います。