feb19.jp

Nobuhiro Takahashi
Designer / Engineer

Papervision3Dでマウスに反応するキューブを作る

Papervision3Dでマウスに反応するキューブを作る

Papervision3Dをはじめてみました。Papervision3Dを導入し、単純に空間にキューブを表示するところから、そのキューブに色や画像をテクスチャとして配置する方法、そして表示するキューブ=3Dオブジェクト(DisplayObject3D)を、「ロールオーバーしたとき」や「クリックしたとき」のようにマウスでイベントを発生させるための方法などなど。

サンプル

導入

まずPapervision3DのExtensionファイルをここからダウンロードします。解凍したパッケージ(srcディレクトリの中身)を、適当なディレクトリに移動します(Windowsなら例えばDドライブ直下に「Classes」っていうフォルダを作ってそこに入れる、とか)。そしてFlash CS3を起動して、編集>環境設定>カテゴリ「ActionScript」>言語: ActionScript3.0設定>クラスパスを、移動先のフォルダ(先ほどの例だと、「D:\Classes」)を指定します。これでPapervision3Dの導入は完了です。

早速「ASファイル」を作成して下記のコードをコピペしてください。

package {
	import flash.events.MouseEvent;
	import flash.events.Event;
	import flash.display.Sprite;
	
	import fl.transitions.Tween;
	import fl.transitions.easing.*;
	
	import org.papervision3d.scenes.*;
	import org.papervision3d.cameras.*;
	import org.papervision3d.objects.*;
	import org.papervision3d.materials.*;
	
	public class Cube3D  {
		private var basemc: Sprite;
		
		private var sp: Sprite;
		private var scene: Scene3D;
		private var camera: Camera3D;
		
		private var material: ColorMaterial;
		//private var material: BitmapFileMaterial;
		private var cube: DisplayObject3D;
		
		public function Cube3D(mc):void {
			basemc = mc;
			init();
		}
		private function init():void {
			init3D();
		}
		private function init3D():void {
			sp = new Sprite();
			basemc.addChild(sp);
			sp.x = basemc.stage.stageWidth / 2;
			sp.y = basemc.stage.stageHeight / 2;
			sp.addEventListener(Event.ENTER_FRAME, enterFrameHandler);
			
			scene = new MovieScene3D(sp);
			
			camera = new Camera3D();
			camera.z = -200;
			
			material = new ColorMaterial(0x666666, 100);
			//material = new BitmapFileMaterial( "ico.gif" );
			var c = new Cube( material, 100, 100, 100, 4, 4)
			cube = scene.addChild(c);
			
			setBtn();
		}
		private function setBtn():void{
			cube.container.buttonMode = true;
			cube.container.addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
			cube.container.addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
		}
		private function rollOverHandler(e:MouseEvent):void {
			new Tween(e.target, "scaleX", Elastic.easeOut, e.target.scaleX, 2, 20, false);
			new Tween(e.target, "scaleY", Elastic.easeOut, e.target.scaleY, 2, 20, false);
		}
		private function rollOutHandler(e:MouseEvent):void {
			new Tween(e.target, "scaleX", Elastic.easeOut, e.target.scaleX, 1, 20, false);
			new Tween(e.target, "scaleY", Elastic.easeOut, e.target.scaleY, 1, 20, false);
		}
		private function enterFrameHandler(e:Event):void{
			cube.rotationX += sp.mouseY / 100;
			cube.rotationY += sp.mouseX / 100;
			
			scene.renderCamera( camera );
		}
	}
}

これをCube3D.asなんて名前で、デスクトップでも何でも適当な場所に保存。

そして今度はFlashファイル(AS 3.0)を作成し、1フレーム目に以下のフレームアクションを記述します。

var s = new Cube3D(this);

実行してみてください。灰色のキューブが空間上でマウスの位置に応じて回転し、ロールオーバーすると拡大、アウトすると元の大きさに戻るというサンプルができました。ちなみにmaterialのコメントアウトを交代させてBitmapFileMaterialで任意のファイル名にすると、外部画像をテクスチャにすることができます。試してみてください。

解説

ではこれをコードの上から順番に細かく分析してみましょう。

package {
	import flash.events.MouseEvent;
	import flash.events.Event;
	import flash.display.Sprite;
	...

今回のサンプルで使用するクラスをインポートします。今回はマウスイベントクラスとイベントクラス、スプライトクラスに、マウスオーバー/アウトしたときに起こすアニメーション用にトゥイーンクラスとイージングクラス、そしてPapervision3Dの「シーン」、「オブジェクト」、「カメラ」、「マテリアル」クラスをインポートします。

public class Cube3D {
	private var basemc: Sprite;
	
	private var sp: Sprite;
	private var scene: Scene3D;
	private var camera: Camera3D;
	
	private var material: ColorMaterial;
	//private var material: BitmapFileMaterial;
	private var cube: DisplayObject3D;

Cube3Dクラスのメンバ変数を宣言しています。

public function Cube3D(mc):void {
	basemc = mc;
	init();
}
private function init():void {
	init3D();
}

コンストラクタです。DisplayObjectContainerを引数にもち、それをbasemcに代入してそれに本クラスで作成する3D空間をaddChildするので、本クラスが外部のインスタンスを汚染するのを防ぐことができます。そして「init関数」を呼び出しています。

init関数では「init3D関数」を呼び出しています。

private function init3D():void {
	sp = new Sprite();
	basemc.addChild(sp);
	sp.x = basemc.stage.stageWidth / 2;
	sp.y = basemc.stage.stageHeight / 2;
	sp.addEventListener(Event.ENTER_FRAME, enterFrameHandler);

3Dオブジェクトを生成するinit3D関数です。少しずつ細かく解説していきます。まず3D空間の土台となるスプライト「sp」を作成して、それをbasemcにaddChildします。spはステージの中央に配置します。また、毎フレーム「enterFrameHandler関数」を呼び出すようにします。

scene = new MovieScene3D(sp);

spをMovieScene3Dコンストラクタの引数にしてMovieScene3Dインスタンス「scene」を作成します。これが3D用の「空間」となります。ちなみにMovieScene3Dではなく、Scene3Dというものもあるのですが、3Dオブジェクトがマウスに反応するようにするにはMovieScene3Dでなければなりません。

camera = new Camera3D();
camera.z = -200;

Camera3Dインスタンス「camera」を生成します。文字通りの「カメラ」で、これのx、y、zプロパティや、focus、zoomプロパティを変更すると、視点、視野、つまり表示が変化します。

material = new ColorMaterial(0x666666, 1);
//material = new BitmapFileMaterial( "ico.gif" );

3Dオブジェクトの皮膚、表面、テクスチャとなるmaterial(素材)を作ります。ColorMaterialの場合、第一引数にカラー、第二引数に透明度(0~1)を与えます。BitmapFileMaterialの場合、引数に外部画像のファイルパスを与えます。ここでは灰色の不透明なColorMaterialインスタンスが生成されています。

	var c = new Cube( material, 100, 100, 100, 4, 4, 4)
	cube = scene.addChild(c);
	
	setBtn();
}

Cubeインスタンス「c」を生成します。引数は、第一引数から順番に、「Material(素材)、「面の幅」、「面の奥行き」、「面の高さ」、「幅の分割数(ポリゴン数的な感じ)」、「奥行きの分割数」、「高さの分割数」。ここでは100-100-100の4-4-4なので、正立方体になっていますが、100-150-200なんて感じにすれば直方体も作れます。また、ここでは分割数を4-4-4としていますが、やはり分割数をあげればあげるほど処理は重くなりますので、基本的には1-1-1がいいと思います。

このcをsceneにaddChildし、返り値をcubeに代入しておきます。次にsetBtn関数(このオブジェクトにマウスイベントを設定する関数)を呼び出しています。

private function setBtn():void{
	cube.container.buttonMode = true;
	cube.container.addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
	cube.container.addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
}

cube.containerプロパティに対してマウスイベントを設定します。ロールオーバーすると「rollOverHandler関数」、ロールアウトすると「rollOutHandler関数」を呼び出します。

private function rollOverHandler(e:MouseEvent):void {
	new Tween(e.target, "scaleX", Elastic.easeOut, e.target.scaleX, 2, 20, false);
	new Tween(e.target, "scaleY", Elastic.easeOut, e.target.scaleY, 2, 20, false);
}
private function rollOutHandler(e:MouseEvent):void {
	new Tween(e.target, "scaleX", Elastic.easeOut, e.target.scaleX, 1, 20, false);
	new Tween(e.target, "scaleY", Elastic.easeOut, e.target.scaleY, 1, 20, false);
}

ロールオーバーしたときとロールアウトしたときのアニメーションをそれぞれTweenクラスを用いて作りました。バネのようなイージング(アニメーション具合)で拡大縮小のアニメーションを行います。

private function enterFrameHandler(e:Event):void{
	cube.rotationX += sp.mouseY / 100;
	cube.rotationY += sp.mouseX / 100;
	
	scene.renderCamera( camera );
}

毎フレーム起こるイベントです。3D空間の土台となるスプライト「sp」からマウスまでの距離によって、cubeを回転させています。Cubeインスタンスなど、全ての3DオブジェクトはrotationX,Y,Zのプロパティを持ちます。

最後にcameraからsceneを映します。

以上です。これらがPapervision3Dの基本となる作り方になると思います。

まとめ

Cubeの代わりにPlaneなど、様々なDisplayObject3Dが用意されていて使うことができるので、このコードを足がかりにいろんなオブジェクトを空間に浮かべてみてください。また、Flashで作ったライブラリに存在するMovieClipをMaterialで表示することもできたりしますので色々試してみてください。

なお、この方法はPapervision3D version.1.5による方法で、バージョンアップなどがあった場合はやり方がかわってくるかもしれませんのであしからず。

Tweet Share Bookmark

Navigation

prev: MOLESKINE DIARY 2008 登場
next: AsBroadcasterを使ってメニューを作る

Recently Entries