なんだか長ったらしいイケてない名前ですが、SpaceNavigatorを使って3D物体や3D空間をグリグリできるようにしました。jit.gl.handleの代わりに使うことができます。いつものように、ダウンロードはサイドバーのaka.objectsからどうぞ。

操作感はさすがに気持ちいいです。ぐるんぐるん、ひゅんひゅん、って感じ。回転させると操作が分かりにくくなるので、もうちょっとナビゲーションを洗練させたいところ、要研究ですね。
なんだか長ったらしいイケてない名前ですが、SpaceNavigatorを使って3D物体や3D空間をグリグリできるようにしました。jit.gl.handleの代わりに使うことができます。いつものように、ダウンロードはサイドバーのaka.objectsからどうぞ。

操作感はさすがに気持ちいいです。ぐるんぐるん、ひゅんひゅん、って感じ。回転させると操作が分かりにくくなるので、もうちょっとナビゲーションを洗練させたいところ、要研究ですね。
OpenGLのフィードバックに続いて、今回はOpenGLのレコーディング、つまり、OpenGLの描画を記録してムービー・ファイルにする方法です。実は、3月に映像作品の上映が予定されていて、これがなんと初体験のDVD納品(=ノン・インタラクティブ)なものだがら、いろいろと研究しているところです。フツーの映像作家や音楽家にとっては簡単なことが、インタラクティブ系の人には面倒だったりしますが、これはその典型ですね。
というわけで、学生クエストならぬ自分クエストであるOpenGLのレコーディングとして、4つの方法を考えました(他にもあったら教えてね)。
(1) 自力でパッチを作成する。
(2) 他人様のパッチを利用する。
(3) スクリーン・キャプチャを使う。
(4) スキャン・コンバータを使う。
(1)の自力作成に関しては、要はOpenGLが描画した画像をマトリックスにすれば、jit.qt.recordでムービー化できるわけですね。具体的なパッチは次のようになります。ダウンロードはこれopengl-recordingpat.zipです。

このパッチのように、jit.gl.sketchにglreadpixelsメッセージを送っておけば、アーギュメントで指定した名前のjit.matrixからマトリックスを取り出すことができます。ただし、OpenGLとマトリックスはY軸の方向が逆なので、jit.resampなどを使って画像を上下反転する必要があります。
あとはjit.qt.recordでムービーに書き出すだけですけど、qmetroの時間間隔やリアルタイム録画の可否、そしてwriteメッセージでのフレーム・レートを適切に設定する必要があります。変な設定だと、妙に動きが速いムービーになったり、必要以上にファイル・サイズが大きなムービーになっちゃいますよ。このあたりのことは2061:Maxオデッセイ(p.781)参照ね。
ちなみに、jit.qt.videooutでDVテープに記録してもいいですね(同書p.789)。それから、jit.gl.textureにtomatrixメッセージを送って、テクスチャーをマトリックス化できるハズなのですが、私の環境ではうまくいきません。なんでかな? あと、OpenGLフィードバックにも書いたように、ソフトウェア・レンダリング(同書p.839)は処理速度の面で不利な場合が多いと思います。さらに、jit.desktopという反則スレスレ技もありますけど、これも処理速度が遅いのが難点です(同書p.851)。
(2)の他人様のパッチというのは、Randy Jones氏(C74の開発スタッフの一人)が作成したrender_nodeのことです(他にもあるかな?)。
このパッチの特徴は、ノン・リアルタイム処理として、OpenGLの描画を1フレームずつ描きながら、ムービー・ファイルに保存してくれることです。なので、HD画像であろうが、オブジェクトが100万個あろうが、コマ落ちすることなく完璧なムービーを作ってくれます(ホント?)。さらには、動画を自然に見せるモーション・ブラーをかける機能があり、オーディオとの完全な同期が可能です(ということになっている)。

ただし、このパッチが定める方法やドローイング・コンテクストに従ってOpenGLの描画を行う必要があります。これは、それほど難しくはないものの、ちょっと面倒かもしれません。また、レコーディング速度は結構遅いです。これはOpenGLの問題ではなくって、ノン・リアルタイム処理におけるオーディオのディスク書き出しの問題だそうです。あと、当然のことながら、リアルタイムに操作しながら映像を変化させることはできないので、このパッチが用途に合わない場合もあるでしょうね。
【追記】ノン・リアルタムでのオーディオのディスク処理は、Signal Vector Sizeを大きくすると良いみたいです。
(3)のスクリーン・キャプチャは、動画として画面の一部または全体をムービーにしてくれる機能を持ったユーティリティ・ソフトウェアで、Snapz Pro X 2 Movie Capture(US$69)などがありますね。フリーウェアでもあるかな?? command+shift+3を1秒間に30回叩くってのは、多分無理でしょう(笑)。
(4)のスキャン・コンバータは、ビデオカードのVGA出力またはDVI出力をビデオ信号に変換する外部デバイスで、CPUにもGPUにも負担をかけないのが二重丸。以前のPowerBookなどのようにビデオ信号出力があれば、そのままでOK。いずれの場合も、ビデオ信号になればビデオ・デッキなどで録画したり、コンピュータでキャプチャしたりできるわけです。
ただし、比較的安価なSDコンポジット変換だと画質がイマイチだし、Matrox MXOあたりだとHDおよびSDのSDI出力が可能ですけど、SDIを受けるデバイスも必要となり、結構な金額になっちゃいます。モノが増えたりケーブルを繋いだりするのもイヤなので、ま、最後の手段ということで。
今日の学生クエストは、OpenGLの描画結果を加工したい、あるいは、フィードバックさせたい、でございました。例えば、以下はトーラス(+補助軸)が1個存在しているだけですが、描画結果に回転歪みをかけながらフィードバックさせているので、複雑な画像になっています。

2061:Maxオデッセイでは、p.839にマトリックスへレンダリングする方法を紹介しています。マトリックスになれば画像処理もフィードバックも簡単ですね。しかし、この場合はCPUによるソフトウェア・レンダリングになり、処理速度が落ちてしまいます。そこで、GPUによるハードウェア・レンダリングのまま処理を行いたいわけです。
解決策:jit.gl.renderへto_textureメッセージ、jit.gl.textureから描画結果を得る。
うむ〜なんのことやら分かりませんね。取り敢えず、パッチは以下の通りで、ダウンロードはこれopengl-feedbackpat.zipです。

ポイントはjit.gl.renderにbangを送ってレンダリングした画像を、to_textureメッセージでテクスチャーに転送していることです(bangbangの1番目)。どのテクスチャーかはusetextureで指定し、ここではtexという名前でloadmessを使って自動設定しています。
このテクスチャーは、texをnameアトリビュートで指定したjiit.gl.textureから出力され、jit.gl.imageunitで加工した後、jit.gl.videoplaneに貼付けて表示します(bangbangの3番目)。この画像は1フレーム前の画像として描画され、その上にjit.gl.gridshapeによって新しいトーラスを描きます(bangbangの2番目)。
ここでのテクチャーはJitter 1.6から新たに加わったもので、OpenGL(GPU)上の画像データと考えれば良いでしょう。テクチャーが流れるパッチコードは水色になります。
以上を繰り返すことによって、OpenGLでレンダリングされた画像を加工しつつ、フィードバックさせているのが、このパッチでの処理です。テクスチャーとして処理しているので、GPU上でデータの遣り取りが行われており、CPUへの負荷はほとんどかかっていないハズです。
ちなみに、jit.gl.imageunitを省略すれば、単純なフィードバックになります。また、jit.gl.videoplaneの位置、大きさ、回転、透明度などを変えることで、フィードバックの起こり方が変わります。また、jit.gl.videoplane自体も3次元物体なので、トーラスを交わらせるとトーラスの一部が切り取られます。これがイヤなら、jit.gl.videoplaneを十分遠くに置いて、ウィンドウに合うように大きくすれば良いと思います。あるいは、他の物体を十分手前に置くことでもいいです。
暇なのか?と言われそうですが(笑)、新しいオブジェクトを作りました。MacBook ProやPowerBook G4(の後期機種)についている環境光センサー(Ambient Light Sensor)の感度を知りたくって、WEBをサーチしたらコードがあったので、即オブジェクト化。ついでに、LCDやキーボードのバックライトもコントロールできるようにしました。開発自体は1時間ほどで済みましたけど、ヘルプ・パッチを作る方が時間がかかりますね
ダウンロードは例によって、サイドバーにあるaka.objectsからどうぞ。

それで、肝心の環境光センサーの感度は、まぁまぁです。シビアな演奏には使えそうもなくって、一発ネタに使える程度かな。それから、PowerBook G4では微妙に動作が変ですけど、まぁいいでしょ。あと、スリープ・ライトや内蔵iSightの緑ランプもコントロールしたいところなのですが…
ダンス公演が終わって、ちょっと時間の余裕ができたので、SpaceNavigatorのオブジェクト(アブストラクション)を作りました。と言っても、やっていることはhiオブジェクトの出力をrouteオブジェクトで振り分けているだけです。
ダウンロードは、サイドバーのソフトウェアにあるaka.objectsからどうぞ。もちろん、ドライバをインストールしてからね。XPでは試していないけど、そのまま動くんじゃないかな?

実際に操作して面白いのは、例えば左に傾けているつもりでも、厳密な操作はできないから、他のパラメータも微妙に増減することです。マウスを左に動かしていても、多少は上下に動いてしまうことと同じですね。このあたりをうまく使えば、味のあるユーザ・インターフェースが作れそうです。
またまた学生クエストから、MaxからAppleScriptを実行するにはどうしたらいいんでしょう?という質問(記事ネタが増えて嬉しい)。tap.applescriptオブジェクトってのが手っ取り早いですが、それが含まれるTap.Toolsは有料なので、できればフリーで実現したいところ。
解決策:aka.shellオブジェクトでosascriptコマンド
aka.shellはShellスクリプト(Unixコマンド)を呼び出すMaxオブジェクトで、osascriptはAppleScript(またはOSAスクリプト)を呼び出すUnixコマンドです。オーバヘッドがどのくらいなのかは試していませんが、超高速な呼び出しが必要でなければ実用になるハズ。
osascript [-l language] [-e command] [-s flags] [programfile] [argument …]
詳しくは、ターミナルでmanしてください。
ちなみに、aka.shellと同等の機能を持つshellオブジェクトもあります。aka.applescriptがあってもいいんですが、自分が必要とするまでは作らないです(笑)。
それから、AppleScriptからShellスクリプトを呼び出すには、do shell scriptというAppleScriptコマンドでOK。となると、MaxからShellスクリプトを呼び出して、その中からAppleScriptを実行して、その中から別のShellスクリプトを立ち上げて…と訳の分からないこともできます。もちろん、無限ループに陥ることもできるハズです。
意外に知られていないのかも、と思ったので書いておきます。
現時点でMax/MSPはバージョン4.6.2、Jitterはバージョン1.6.2が最新ですが、通常新しいバージョンがリリースされるまでに結構日数がかかります。その間にバグなどが発見されて対応が行われたオブジェクトは、インクリメンタル・ダウンロードのページに掲載されるようになっています。ですから、オブジェクトの動作が明らかにおかしいという場合は、まずココをチェックするといいと思いますよ。
UBオブジェクト開発講座に引き続き、今回からはJitterオブジェクトの開発方法を手っ取り早く見ていきます。もちろん、ユニバーサル・バイナリーとしての開発方法です。より詳しい説明はCycling ’74のWEBサイトの「Jitter SDKページ」にあります。このページからは、Jitter API ReferenceとJitter Programming Guideを参照することができ、SDKファイルをダウンロードすることができます。
さて、Jitterオブジェクト開発講座の第1回はSDK(ソフトウェア・デベロップメント・キット)のインストールとサンプルのビルドまで、です。以前のUBオブジェクト開発講座に近い形で書いてみますね。
Step 1: Xcodeをインストールする。
・Jitterブジェクトの開発には、Xcode 2.2以降とMac OS X 10.3.9以降が必要である。
(なぜかUBオブジェクト開発はXcode 2.2.1以降とMac OS X 10.4が必要となっている。いずれも最新のバージョンを用意した方が良いと思われる。)
・XcodeはMac OS XのインストールDVDに付属している他、最新版はApple社の開発者用サイトからダウンロードできる。
Step 2: SDKをコピーする
・ Cycling ’74社のWebサイトからJitter 1.6 Macintosh SDKをダウンロードする。
・Jitter1.6SDKディスクの内容をハードディスクの任意の場所にコピーする。例えば、Jitter SDKというフォルダを作り、Jitter1.6SDKディスクの内容をJitter SDKフォルダにコピーすると良い。
Step 3: フレームワークをコピーする
・Jitter1.6SDKフォルダのCopyContentsToLibraryFrameworksフォルダの中身をLibrary/Frameworks/フォルダにコピーする。
(Libraryフォルダは日本語環境では起動ディスクの「ライブラリ」フォルダのこと。)
(OpenGLを利用する場合は、OpenGL.frameworkが必要となるが、これはXcodeの一部として既にインストールされている。)
Step 4: サンプルをビルドする
・サンプルのプロジェクト・ファイルをダブル・クリックする。例えば、projectsフォルダにあるhelloフォルダのmax.jit.hello.xcodeprojファイルをダブル・クリックする。
・Xcodeが起動し、プロジェクト・ウィンドウが開く。
・Xcodeのプロジェクト・ウィンドウのビルド・アイコンをクリックして、プロジェクトをビルドする。
・ビルドが成功すれば、helloフォルダにbuildフォルダが作られるが、その中のDevelopmentフォルダにjit.hello.mxoというオブジェクトが作られる。ただし、これはエイリアスで、実際のファイルはJitter SDKフォルダと同じ階層に作られるsysbuildフォルダの中のDevelopment:Cycling ’74:jitter-externalsフォルダにある。
・何らかのエラーが発生する場合は、Jitter SDKの構成やフレームワークのコピーが間違っていることが考えられるので、再確認する。
・オブジェクト・ファイルが作成できれば、Maxを起動してオブジェクトの動作を確認する。sysbuildフォルダ下のjitter-externalsフォルダにjit.hello.help(あるいはjit.hello-test.patなど)といったテスト用のパッチ・ファイルを作ると良い。
Step 5: 自分のプロジェクを変換する
・サンプルのプロジェクトを複製し、それを元にユニバーサル・バイナリ化したい自分のプロジェクト、あるいは新しく制作するプロジェクトを作ると良い。詳しくは、Jitterオブジェクト開発講座(2)にて説明。
ところで、すでにMaxMSP UB SDKをインストールした人は、同じフォルダにJitter SDKもまとめたくなると思いますが、現状では別々のフォルダにしたほうが良いようです。例えば、max-includesフォルダの内容って微妙に違いますからね。
私はユーザ・フォルダ(akaフォルダ)にdevelopmentという開発関係のファイルを入れるフォルダを作り、その中にJitter SDKフォルダやMaxMSP UB SDKフォルダを入れています。以下の図のように、同じ階層にsysbuildフォルダが作られることになります。また、Jitter SDKフォルダ下に自分のプロジェクを入れるフォルダを作ると良いでしょう。私の場合はaka-jit-ub-projectsフォルダがそれです。

学生がお正月に悩んでいたらしいのですが、jit.gl.multipleを使って以下のような3次元配置をしたかったんだそうです

それで、2次元配置なら、ヘルプ・パッチにもあるように、
jit.matrix 3 float32 4 4
↓
jit.expr @expr “snorm[0]” “snorm[1]”
ってな感じで位置情報をjit.gl.multipleに送ればいいので、これを3次元に拡張すると、
jit.matrix 3 float32 4 4 4
↓
jit.expr @expr”snorm[0]” “snorm[1]” “snorm[2]”
で良さそうなんだけど、これがうまく行かない。いろいろと試してみたところ、やはり3次元以上のマトリックスに対応していない気配が濃厚。そこで、取りあえずの解決策として考えたのは、1次元配列で位置情報を自前で計算する方法。ディメンションの大きさが異なれば、計算式も修正しなければならないのがイマイチなのですが….(jit.exprまでにマトリックスの大きさを取得して、その3乗根を第2インレットに送るとか?)
jit.matrix 3 float32 64
↓
jit.expr @expr “cell[0]%4 – 1.5” “floor(cell[0]/4)%4 – 1.5” “floor(cell[0]/16) – 1.5”

パッチのダウンロードは以下のリンクからどうぞ。
jitglmultiple-samplepat.zip
後でMaxMSP-MLで尋ねたところ、”jit.gl.multiple only processes 2 dimensional matrices right now.”との返事でした。でも、そんなこと、どこにも書いていないのでは??
ちなみに、jit.exprはとっても便利なので、そのうち2061:Maxオデッセイ補完計画で取り上げようと思ってました。
うぉ、なんか吹雪いてますね…..1月公演では自前のパーティクル・システムもどきを作っていて、これが吹雪みたいな表現にも使えるんですけど(ってのは強引な引っ掛け)、制作途中にjit.opでの計算がうまくいかなくって四苦八苦してたら、jit.opのバグだったという話です。

上図のように、%(割り算の余り)はきちんと計算されていますが、fold(折り返し型の余り)やwrap(包み込み型の余り)は無茶苦茶な結果になっていますね。ありゃりゃらと思って、MaxMSP-MLを検索してみると、既知のバグで次バージョンで解決見込みとなっていました(早く出してね〜)。
てなわけで今回は、どんなシステムにもバグがあるからね(ただし99%は自分のバグ)っていう話と、マトリクス演算は膨大な計算量でバグ探しが大変なんだけど、上図のような単純化したパッチで検証すればいいんじゃないかなという提案でした。