Max/MSP / Processing

Archives

mxj を.app(.exe) ビルド時の注意点

2010.11.6 土曜日

mxjのライブラリを使ったMax/MSPを.app(.exe)でビルドし、そのまま実行するとJavaの実行環境がインクルードされていないためにうまく動かない場合があります。Maxウィンドウには下記エラー表示。
・(mxj) Unable to find max.jar! mxj is rendered powerless in its absence.
・Unable to create JVM
これの解決方法を紹介。

Macの場合、ビルドされた■■■.appを右クリックして「パッケージの内容を表示」し「Contents/support」フォルダ内に「java」フォルダを新規作成。その中に「アプリケーション/Max5/Cycling ’74/java」フォルダ内にある以下のファイルをコピー。
・classes/■■■.class *使用しているライブラリ
・classes/■■■.java
・lib/max.jar
・max.java.config.txt

Windowsの場合も似たディレクトリになっているので、同じようにファイルをコピー。
これでちゃんと実行されるはず。

注意点は、「コレクティブ / アプリケーションをビルド…」をすると、「含めるフォルダ…」などでインクルードするファイルを指定できますが、上記ファイルを指定してもインクルードされない上に、後でビルドされたアプリにmax.jarをコピーしてもうまく認識されなくなります。なのでmxj関連のファイルは指定しないようにしておきましょう。

上記の環境はMac、WinともにMax5.1.4です。

Posted by tmdf||comments (0)

起動時にMaxウィンドウ非表示

2010.11.4 木曜日

タイトルの通り、.mxf や.app(.exe)のMax/MSPの実行ファイルを起動した場合に、Maxウィンドウを表示させない方法の紹介。

「standalone」オブジェクトを作り、「インスペクタ」で「Status Window Visible at Statup」をオフにするだけ。

Posted by tmdf||comments (0)

Windows7での.mxf(Max/MSP)不具合

2010.5.6 木曜日

Twitterの方に数ヶ月前に書いたのですが、忘れそうなので投稿しておきます。
※Windows7のPCが手元になくなってしまったので試せませんが、最新のRuntimeを使えばこの不具合が直っているかも。

Max/MSPでビルドしたmxfファイルを、Windows7のRuntime(ver 5.1.3)で実行すると初回起動以降(初回はうまく動作します)、オーディオのI/Oデバイスが認識されなくなる(DSPステータスみるとDriverが「None」)場合の対処法。

手動で毎回ステータス画面を開いて設定するのは面倒なので、まず「admme@.txt」っていうファイルを検索して消去。次に、このファイルが入っていた「Max 5 Preferences Files」フォルダ(最初は不可視)を書き込み不可に。以上の2ステップです。
強制的に初期設定ファイルを作れないようにするだけですが、これで意図したとおりに動作してくれるはず。フォルダを書き込み不可にしたことによって、他の不具合が発生するかもしれないので、その場合は権限を調整して下さい。

Posted by tmdf||comments (0)

Flash間データ通信:Socket

2009.10.2 金曜日

異なるPCで起動しているFlash間で通信を行いたい場合、TCPのソケットサーバーを間に立て、Socket通信を行うのがベストだと思います。FLASHはTCPといった遅い通信プロトコルを採用しているため、処理の重いString型を扱うXML Socket通信より、ByteArray型を扱うSocket通信を使った方が、若干スピードのメリットがあります。

話は逸れますが、Flashの扱えるTCPは信頼性>速度の通信プロトコルのため、データを確実に送ることはできますが、大容量のデータを送り続けた場合には数十秒のタイムラグが発生します。現在のFlashでは扱えないUDPは、信頼性<速度の通信プロトコルなので、いつかサポートしてほしいところです。プロトコルの詳しい情報はWikipediaの「TCP」と「UDP」などをご覧ください。

修正 2010.8.13
AIR2.0からUDPのサポート、TCPサーバー(以前はクライアントだけ)にもなれます。

Flashの間に立てるソケットサーバーですが、フリーウェアでは「Socket Debugger (Free)」があります。このソフトウェアはバッファサイズが99,999Byteが限度のようなので、大きいデータのリアルタイムなやりとりには向きませんが、ちょっとしたテスト環境の構築には便利です。

また、単純なTCPサーバーならProcessingでも作れます。下記コードでは「Flash clientA」からポート3000を通して「Processing serverA」にデータを送り、受信したデータを「Processing serverB」からポート3001経由で「Flash clientB」に戻しています。動作検証用のサンプルなので、同じPC内(localhost)にサーバーとクライアントの全てを起動させていますし、接続確認や細かいエラー処理などは省いています。Processing → FLASHの順に起動し、FLASHの画面をクリックするとデータの送受信を行います。

//Server.pde
import processing.net.*;

//サーバー変数
Server serverA;
Server serverB;

//初期設定
void setup() {

	//サーバーの作成
	serverA = new Server(this, 3000);
	serverB = new Server(this, 3001);
}

//常時実行
void draw() {

	//serverAに接続しているクライアントを取得
	Client client = serverA.available();

	//クライアントがいた場合
	if (client != null) {

		//データを取得
		String data = client.readString();

		//データがある場合
		if (data != null) {

			//serverBに書き込み
			serverB.write(data);
		}
	}
}
//Client.as
package {
	import flash.display.MovieClip;
	import flash.events.MouseEvent;
	import flash.events.ProgressEvent;
	import flash.net.Socket;

	public class Client extends MovieClip {

		//クライアント変数
		private var clientA:Socket;
		private var clientB:Socket;

		//初期設定
		public function Client():void {

			//リスナー登録
			stage.addEventListener(MouseEvent.CLICK, Send);

			//clientA serverAに接続
			clientA = new Socket();
			clientA.connect(&amp;quot;localhost&amp;quot;, 3000);

			//clientB serverBに接続、リスナー登録
			clientB = new Socket();
			clientB.addEventListener(ProgressEvent.SOCKET_DATA, Recieve);
			clientB.connect(&amp;quot;localhost&amp;quot;, 3001);
		}

		//データ送信
		private function Send(e:MouseEvent):void {

			//データを書き込み
			clientA.writeUTFBytes(String(Math.random()));

			//serverAに送信
			clientA.flush();
		}

		//データ受信
		private function Recieve(e:ProgressEvent):void {

			//受信した文字データを出力
			trace(clientB.readUTFBytes(clientB.bytesAvailable));
		}
	}
}

Posted by tmdf| |comments (0)

Processingでレイヤー表現

2009.7.1 水曜日

Processingでレイヤーっぽくオブジェクト同士が重なった表現をする場合、z座標を使って重なりを調整すると思うけど、カメラ位置とオーバーラップする3Dオブジェクトを配置すると、常に最前面に表示させたいメニューより前面に描画され、意図しない(調整しずらい)表示になったりします。

同階層に200x200pxの「Sample.png」という画像ファイルがあるとして、以下のようなプログラムで、png画像よりboxオブジェクトが前に来てしまう現象。

void setup() {
	size(200, 200, P3D);
}

void draw() {
	background(0);

	translate(100, 100, 0);
	box(100, 100, 100);

	translate(-100, -100, 0);
	PImage b = loadImage("Sample.png");
	image(b, 0, 0);
}

そこで、png画像を常に最前面に表示できないか試行錯誤した結果、PGraphicクラスを使ってレンダリングした画像を貼り付ける、または最前面に表示させたいオブジェクトを3Dオブジェクトより自分に近づける、この2つが今のところの解決方法。

まず、PGraphicクラスを使う場合。これは単純にPGraphics(仮の描画ステージ)でオブジェクトを描いてレイヤーっぽく貼り付けていく。でも、半透明や大きなサイズで使ったり、負荷が重そうな処理をすると、思った以上に描画速度が落ちていくので注意。プログラムは下記。

void setup() {
	size(200, 200, P3D);
}

void draw() {
	background(0);

	PGraphics pg = createGraphics(200, 200, P3D);
	pg.beginDraw();
	pg.background(0);
	pg.translate(100, 100, 0);
	pg.box(100, 100, 100);
	pg.endDraw();
	image(pg, 0, 0);

	PImage b = loadImage("Sample.png");
	image(b, 0, 0);
}

次にオブジェクトを自分に近づける方法。前者より負荷は少ないけど、最前面オブジェクトより前に表示、最前面オブジェクトが表示されない、ドットバイドットで表示しづらい、などがあるので微調整しながら使わないといけない。プログラムは以下のような感じ。変数cは等倍で表示できた距離、dはカメラを引き寄せと画像を同じだけ縮小するための変数。

float c = 175;
float d = 20;

void setup() {
	size(200, 200, P3D);
}

void draw() {
	background(0);

	camera(0, 0, c, 0, 0, 0, 0, 1, 0);
	box(100, 100, 100);

	camera(0, 0, c / d, 0, 0, 0, 0, 1, 0);
	imageMode(CENTER);
	PImage b = loadImage("Sample.png");
	image(b, 0, 0, b.width / d, b.height / d);
}

Posted by tmdf||comments (0)

traer.animation

2009.6.10 水曜日

以前、Processingのトゥイーンアニメーションライブラリ「Shapetween」について少し触れたけど、同じようなライブラリで「traer.animation」ってのを発見しました。

Shapetweenと違うのは、トランジションなど細かい設定が全く無くて、ちょっとスムージングしたい場合ぐらいしか使いようがないこと。使い方はShapetweenと同じように、数を扱うスムージングオブジェクト(下記プログラムでいうscl)を、他のオブジェクトのプロパティに設定していくイメージ。Smoother、Smoother2D、Smoother3D と3種類のスムージングクラスがあるけど使い方は同じで、一度に扱える数値が1個~3個の違いだけ。

以前と同じように、マウスダウンで赤い円の大きさが変化するサンプルプログラム。

//Main.pde
import traer.animation.*;

Smoother scl;
Animator ani;

//設定
void setup() {

	//スムージング設定
	//引数は、0がダイレクトで、1に近づくほどゆっくり
	ani = new Animator(0.95);

	//スムージング変数とアニメーションを関連付け
	//目標値を設定
	scl = ani.makeSmoother();
	scl.setTarget(100);

	//描画設定(線なし、塗り赤)
	noStroke();
	fill(255, 0, 0);
}

//描画
void draw() {

	//初期化
	background( 255 );

	//アニメーション経過
	ani.tick();

	//円を描画
	ellipse(width / 2, height / 2, scl.getValue(), scl.getValue());
}

//マウスが押された場合
void mousePressed() {

	//リセット、目標値を再設定
	scl.setValue(0);
	scl.setTarget(100);
}

Posted by tmdf||comments (0)

Processingでメモリ不足

2009.6.5 金曜日

Processingは大きく分けて3つの描画方式(P2D、P3D、OpenGL)があって、今回はOpenGLで描画する際にフリーズする現象について報告。
Processing1.0.4(1.0.3でも同様)で、Windows XP SP3、Core2Quad 3GHz、GeForceGTS 250、RAM 4GB(3GB) と、MacOS 10.5.7、Core2Duo 2GHz、RadeonHD2400、RAM 2GB。

連番画像を読み込んで、パラパラ漫画の要領で表示しようとすると、あるデータ量でメモリ不足でフリーズ。エラーメッセージは「OutOfMemoryError」。だいたい30MB(6000x5000pixel)くらいのデータを使おうとした時で、Windows、Macどちらも同じ感じ。ファイルのデータ量ではなく解像度に依存しているみたいで、高圧縮JPEG、無圧縮PNGどちらでも同じ解像度のデータで起きる。
タスクマネージャやアクティビティモニタでは、メモリデルタとかフォルトが起きまくってメモリ使用量が急激に上がってしまう模様。下記プログラムの10行目の size() の第3引数を”P2D”や”P3D”にすると常識的なメモリ使用量で収まるし、問題なく動作するので”OPENGL”を使おうとした時のみの現象だと思う。

追記 2009.6.9
解決方法:パラパラ漫画みたいに同時に使用する画像が限られている場合は、数枚だけ先読みして、変数を使いまわしつつ、System.gc(); を使ってメモリ開放(ガベージコレクション)するとフリーズしない。一度に大量のテクスチャを使用するような状況では使えない方法だけど、上手くファイル管理できればそれなりの画像数は使えるみたい。あと、下記プログラムみたいに常にメモリ開放しながらだと実行速度(FPS)が遅いので、メモリーを監視しつつタイミング良く処理して下さい。

動作プログラムは下記。実行環境と同階層に「image」フォルダがあって、フォルダ内に「0 ~ 100.png」の画像ファイルがある状況で、4枚分の画像を先読み。

//Main.pde
import javax.media.opengl.*;
import processing.opengl.*;

int a = 0;
int b = 5;
PImage [] img = new PImage[b];

void setup() {
	size(800, 600, OPENGL);
	frameRate(100);
	noSmooth();

	for(int i = 0; i < b; i ++) {
		String url = "image/" + str(i) + ".png";
		img[i] = loadImage(url);
	}
}

void draw() {
	background(0);

	image(img[a], 0, 0, img[a].width, img[a].height);

	b++;
	if (b == 100) {
		b = 0;
	}

	String url = "image/" + str(b) + ".png";
	img[a] = loadImage(url);

	a ++;
	if (a == 5) {
		a = 0;
	}

	System.gc();
}

Posted by tmdf| |comments (0)

Shapetween

2009.5.7 木曜日

何か書かないと永遠に放置しそうになるので久しぶりに投稿。
今回はActionScriptじゃなくてProcessingについて。

ActionScriptだと「Tweener」というアニメーションライブラリが有名でとても便利なんだけど、Processingだと「Shapetween」が同じようなライブラリにあたるみたい。このライブラリについて、日本語であまり解説されていないみたいなので、Tweenerとちょっと比べてみました。

まず、考え方で大きく違うのはTweenerはオブジェクト(DisplayObejct?)にアニメーションを指定するのに対して、Shapetweenではそれ自体がオブジェクトだということ。だからShapetweenでは、time()とposition()という2つのメソッドで0〜1までのfloat(ActionScriptだとNumber)を取得し、それを任意のオブジェクトのプロパティなどに代入するといった具合で使います。

描画の概念が違うのでActionScriptと比べること自体ナンセンスな感じがするけど、下のプログラムは、マウスを押すたびに赤い円のサイズが大きくなる両プログラムのサンプル。ActionScriptの方はWonderflに追加してみました。

import megamu.shapetween.*;

Tween tweener;

//設定
void setup() {

	//アニメーション設定
	tweener = new Tween(this, 1, Tween.SECONDS, Shaper.LINEAR);

	//一度だけ実行(リピートしない)
	tweener.setPlayMode(Tween.ONCE);

	//描画設定(線なし、塗り赤)
	noStroke();
	fill(255, 0, 0);
}

//描画
void draw() {

	//初期化
	background(255);

	//円を描画
	ellipse(width / 2, height / 2, tweener.position() * 100, tweener.position() * 100);
}

//マウスが押された場合
void mousePressed() {

	//アニメーション再開
	tweener.start();
}
package {
	import caurina.transitions.Tweener;
	import flash.events.MouseEvent;
	import flash.display.Sprite;

	public class Main extends Sprite {

		private var Circle_mc:Sprite;

		public function Main():void {

			//赤い円を描画
			Circle_mc = new Sprite();
			addChild(Circle_mc);
			Circle_mc.graphics.beginFill(0xFF0000, 1.0);
			Circle_mc.graphics.drawEllipse(0, 0, 1, 1);
			Circle_mc.graphics.endFill();

			//リスナー
			stage.addEventListener(MouseEvent.MOUSE_DOWN, MouseDown);
		}

		//マウスが押された場合
		private function MouseDown(e:MouseEvent):void {

			//アニメーション解除
			Tweener.removeTweens(Circle_mc);

			//サイズを初期化
                        Circle_mc.x = Circle_mc.y = 50;
			Circle_mc.width = Circle_mc.height = 1;

			//アニメーション開始
			Tweener.addTween(Circle_mc, {
				x			:0,
				y			:0,
				width		:100,
				height		:100,
				time		:2.0,
				transition	:"liner"
			});
		}
	}
}

Posted by tmdf| |comments (0)

Photo

PROFILE

森田 考陽 [Takaaki Morita]
Twitter: @tmdf
Other: mtdf.net

Designer / Programmer

RECENT POSTS

MONTHLY ARCHIVES