トップへ戻るニュースフォーラムFLASH-ML 過去ログBak@Flaダウンロードよくある質問と答
ログイン
ユーザ名:

パスワード:


パスワード紛失

新規登録
メインメニュー
メイン
   ActionScript 3.0 特設会議室
     3Dの立方体を正確に回転させるには
投稿するにはまず登録を

スレッド表示 | 新しいものから 前のトピック | 次のトピック | 下へ
投稿者 スレッド
SeeDa!!
Åê¹ÆNo.41288
投稿日時: 2009-1-23 1:26
職人
居住地: Nagoya
投稿: 221
使用環境:
WinXP
Flash CS4
au:W33SA?
3Dの立方体を正確に回転させるには
CS4を手に入れてAS3.0を触り始めました。
簡単なコードで画像を貼った立方体を3D(透視投影)で回転させることができて驚いてます!

正しい作法とはほど遠い下記のコードをフレームに書いて何とかそれっぽく回転してますが、感覚的にちょっと変な動きです。
立方体の右へカーソルを持っていくと右、下へ持っていくと下…というのが少しずれるし、斜め方向はてんで話になりません。

X,Y軸の回転だけで表現してますがZ軸回転をうまく利用すればよいのか、ベクターを便利に使えるのか、敷居の高そうなmatrixに手を出さなければならないのか…、何か助言をいただけると助かります。

/*
 * 立方体をマウスに反応させて回転させるサンプル
 * 各面の基準点は中心に設定してライブラリに登録しておく
 * 6面をrect1?rect6としておき、そのままスクリプト用に書き出す
 */

// 立方体の1辺の長さ
var nearLen:Number = 100;

// 立方体を画面のセンターに配置
var cube:MovieClip = new MovieClip();
addChild(cube);
cube.x = stage.stageWidth/2;
cube.y = stage.stageHeight/2;

// ライブラリにある画像(MC)の位置設定
var face1:MovieClip = new rect1();
face1.z = -nearLen/2;
var face2:MovieClip = new rect2();
face2.z = nearLen/2;
face2.rotationY = 180;
var face3:MovieClip = new rect3();
face3.x = -nearLen/2;
face3.rotationY = 90;
var face4:MovieClip = new rect4();
face4.x = nearLen/2;
face4.rotationY = 270;
var face5:MovieClip = new rect5();
face5.y = -nearLen/2;
face5.rotationX = -90;
var face6:MovieClip = new rect6();
face6.y = nearLen/2;
face6.rotationX = 90;

// 各面を配列に格納
var faces:Array = new Array(face1, face2, face3, face4, face5, face6);

// 立方体を回転
stage.addEventListener(Event.ENTER_FRAME, rotationCube);
function rotationCube(e:Event) {
	// マウス位置から回転スピードを決定
	var dx:Number = stage.mouseX - cube.x;
	var dy:Number = stage.mouseY - cube.y;
	cube.rotationY -= dx / 9;
	cube.rotationX += dy / 9;
	// 予め各面を貼ってそのZ座標を得る
	for (var ind:uint = 0; ind < faces.length; ind++) {
		cube.addChild(faces[ind]);
	}
	// グローバルなz座標を得る
	for (ind=0; ind < faces.length; ind++) {
		faces[ind].pz = faces[ind].transform.getRelativeMatrix3D(root).position.z;
		cube.removeChild(faces[ind]);
	}
	// z座標が立方体より前面にある面だけを描画
	faces.sortOn("pz", Array.NUMERIC | Array.DESCENDING);
	for (ind=0; ind < faces.length; ind++) {
		if (faces[ind].pz < cube.z) {
			cube.addChild(faces[ind]); 
		}
	}
}

過去にAS2.0でゴリゴリ書いたものは思い通りに回転したんだけどなぁ
今回のは作りが簡単すぎ却って手こずってます。っていうか、きっと簡単な方法があるんじゃないかと
野中文雄
Åê¹ÆNo.41289
投稿日時: 2009-1-23 3:11
ちょんまげら
居住地: 東京
投稿: 4531
使用環境:
CS5.5 .6.8 Vista Home Premium (SP1)
Re: 3Dの立方体を正確に回転させるには
インスタンスのデフォルト(初期)状態を起点に、回転が加わっているのではないでしょうか。

参考:「Matrix3Dクラス ? 変換行列2」(とくに02「変換行列を適用する順序」以降)、「変換行列を数学的に捉える」(とくに3「Matrix3Dクラスにおける変換行列の扱い」)
引用:
SeeDaさんは書きました:
立方体の右へカーソルを持っていくと右、下へ持っていくと下…というのが少しずれるし、斜め方向はてんで話になりません。

X,Y軸の回転だけで表現してますがZ軸回転をうまく利用すればよいのか、ベクターを便利に使えるのか、敷居の高そうなmatrixに手を出さなければならないのか…、何か助言をいただけると助かります。


----------------
 

野中文雄
Åê¹ÆNo.41290
投稿日時: 2009-1-23 4:08
ちょんまげら
居住地: 東京
投稿: 4531
使用環境:
CS5.5 .6.8 Vista Home Premium (SP1)
Re: 3Dの立方体を正確に回転させるには
以下の修正を加えると、いかがでしょうか。
引用:
SeeDaさんは書きました:
立方体の右へカーソルを持っていくと右、下へ持っていくと下…というのが少しずれるし、斜め方向はてんで話になりません。
...[中略]...
/*
 * 立方体をマウスに反応させて回転させるサンプル
 * 各面の基準点は中心に設定してライブラリに登録しておく
 * 6面をrect1?rect6としておき、そのままスクリプト用に書き出す
 */

// 立方体の1辺の長さ
var nearLen:Number = 100;

// 立方体を画面のセンターに配置
var cube:MovieClip = new MovieClip();
addChild(cube);
cube.x = stage.stageWidth/2;
cube.y = stage.stageHeight/2;
cube.z = 0;
// ライブラリにある画像(MC)の位置設定
var face1:MovieClip = new rect1();
face1.z = -nearLen/2;
var face2:MovieClip = new rect2();
face2.z = nearLen/2;
face2.rotationY = 180;
var face3:MovieClip = new rect3();
face3.x = -nearLen/2;
face3.rotationY = 90;
var face4:MovieClip = new rect4();
face4.x = nearLen/2;
face4.rotationY = 270;
var face5:MovieClip = new rect5();
face5.y = -nearLen/2;
face5.rotationX = -90;
var face6:MovieClip = new rect6();
face6.y = nearLen/2;
face6.rotationX = 90;

// 各面を配列に格納
var faces:Array = new Array(face1, face2, face3, face4, face5, face6);

// 立方体を回転
stage.addEventListener(Event.ENTER_FRAME, rotationCube);
function rotationCube(e:Event) {
	// マウス位置から回転スピードを決定
	var dx:Number = stage.mouseX - cube.x;
	var dy:Number = stage.mouseY - cube.y;
	// cube.rotationY -= dx / 9;
	// cube.rotationX += dy / 9;
	var nX:Number = cube.x;
	var nY:Number = cube.y;
	cube.transform.matrix3D.appendTranslation(-nX, -nY, 0);
	cube.transform.matrix3D.appendRotation(-dx/9, Vector3D.Y_AXIS);
	cube.transform.matrix3D.appendRotation(dy/9, Vector3D.X_AXIS);
	cube.transform.matrix3D.appendTranslation(nX, nY, 0);
	// 予め各面を貼ってそのZ座標を得る
	for (var ind:uint = 0; ind < faces.length; ind++) {
		cube.addChild(faces[ind]);
	}
	// グローバルなz座標を得る
	for (ind=0; ind < faces.length; ind++) {
		faces[ind].pz = faces[ind].transform.getRelativeMatrix3D(root).position.z;
		cube.removeChild(faces[ind]);
	}
	// z座標が立方体より前面にある面だけを描画
	faces.sortOn("pz", Array.NUMERIC | Array.DESCENDING);
	for (ind=0; ind < faces.length; ind++) {
		if (faces[ind].pz < cube.z) {
			cube.addChild(faces[ind]); 
		}
	}
}


----------------
 

SeeDa!!
Åê¹ÆNo.41291
投稿日時: 2009-1-23 5:27
職人
居住地: Nagoya
投稿: 221
使用環境:
WinXP
Flash CS4
au:W33SA?
Re: 3Dの立方体を正確に回転させるには
まさに探していた回答をいただきありがとうございます。
お陰でとても気持ちよい動きになりました。これを元に色々と発展できそうです。

添削していただいたスクリプトと、ご提示いただいたMatrix3Dクラスの記事を参考にスクリプトを修正したところ、cube.z = 0;を抜かしたためにエラーになったのと、Y軸回転がカーソルの向きと逆になってしまったので赤字部分を修正しました。面の配置方法に問題があったのかな?

Matrix3DクラスはActionScript3.0 プロフェッショナルガイドに載ってませんよね?
もっとも61/640pまでしか読み進んでいませんが
CS4での3Dスゴイです。triangleやらvectorやら、オチオチ寝ていられません。

/*
 * 立方体をマウスに反応させて回転させるサンプル
 * 各面の基準点は中心に設定してライブラリに登録しておく
 * 6面をrect1?rect6としておき、そのままスクリプト用に書き出す
 */

// 立方体の1辺の長さ
var nearLen:Number = 100;

// 立方体を画面のセンターに配置
var cube:MovieClip = new MovieClip();
addChild(cube);
cube.x = stage.stageWidth/2;
cube.y = stage.stageHeight/2;

// ライブラリにある画像の位置設定
var face1:MovieClip = new rect1();
face1.z = -nearLen/2;
var face2:MovieClip = new rect2();
face2.z = nearLen/2;
face2.rotationY = 180;
var face3:MovieClip = new rect3();
face3.x = -nearLen/2;
face3.rotationY = 90;
var face4:MovieClip = new rect4();
face4.x = nearLen/2;
face4.rotationY = 270;
var face5:MovieClip = new rect5();
face5.y = -nearLen/2;
face5.rotationX = -90;
var face6:MovieClip = new rect6();
face6.y = nearLen/2;
face6.rotationX = 90;

// 各面を配列に格納
var faces:Array = new Array(face1, face2, face3, face4, face5, face6);

// 立方体をマウス位置をもとに回転
stage.addEventListener(Event.ENTER_FRAME, rotationCube);
var nX:Number = cube.x;
var nY:Number = cube.y;
var nDeceleration:Number = 0.3;
cube.z = 0;
function rotationCube(e:Event):void {
	var nRotationY:Number = (nX - mouseX) * nDeceleration;
	var nRotationX:Number = (mouseY - nY) * nDeceleration;
	cube.transform.matrix3D.appendTranslation(-nX, -nY, 0);
	cube.transform.matrix3D.appendRotation(nRotationY, Vector3D.Y_AXIS);
	cube.transform.matrix3D.appendRotation(nRotationX, Vector3D.X_AXIS);
	cube.transform.matrix3D.appendTranslation(nX, nY, 0);
	// Z座標を取得するために各面を配置
	for (var ind:uint = 0; ind < faces.length; ind++) {
		cube.addChild(faces[ind]);
	}
	// 各面のグローバルなz座標を取得
	for (ind=0; ind < faces.length; ind++) {
		faces[ind].pz = faces[ind].transform.getRelativeMatrix3D(root).position.z;
		cube.removeChild(faces[ind]);
	}
	// z座標が立方体より前面にある面だけを描画
	faces.sortOn("pz", Array.NUMERIC | Array.DESCENDING);
	for (ind=0; ind < faces.length; ind++) {
		if (faces[ind].pz < cube.z) {
			cube.addChild(faces[ind]); 
		}
	}
}
野中文雄
Åê¹ÆNo.41293
投稿日時: 2009-1-23 13:46
ちょんまげら
居住地: 東京
投稿: 4531
使用環境:
CS5.5 .6.8 Vista Home Premium (SP1)
Re: 3Dの立方体を正確に回転させるには
Matrix3Dクラスは、Flash Player 10の実装ですので、収録には間に合いませんでした。具体的に日程は決まっていませんけど、つぎに改訂するときは解説に含め、行列の数学的な説明もかなり補うつもりです。
引用:
SeeDaさんは書きました:
Matrix3DクラスはActionScript3.0 プロフェッショナルガイドに載ってませんよね?

それだけでは何ですので、掲載いただいたスクリプトの関数rotationCube()に少しチューニングを加えてみました。実測はしていませんが、多少効率が上がっていると思います。
function rotationCube(e:Event):void {
	var nRotationY:Number = (nX - mouseX) * nDeceleration;
	var nRotationX:Number = (mouseY - nY) * nDeceleration;
	var myMatrix3D:Matrix3D = cube.transform.matrix3D;
	myMatrix3D.appendTranslation(-nX, -nY, 0);
	myMatrix3D.appendRotation(nRotationY, Vector3D.Y_AXIS);
	myMatrix3D.appendRotation(nRotationX, Vector3D.X_AXIS);
	myMatrix3D.appendTranslation(nX, nY, 0);
	cube.transform.matrix3D = myMatrix3D;
	// Z座標を取得するために各面を配置
	for (var ind:uint = 0; ind < faces.length; ind++) {
		cube.addChild(faces[ind]);
	}
	var face_mc:MovieClip;
	// 各面のグローバルなz座標を取得
	for (ind=0; ind < faces.length; ind++) {
		face_mc = faces[ind] as MovieClip;
		// faces[ind].pz = aces[ind].transform.getRelativeMatrix3D(root).position.z;
		face_mc.pz = face_mc.transform.getRelativeMatrix3D(root).position.z;
		// cube.removeChild(faces[ind]);
	}
	// z座標が立方体より前面にある面だけを描画
	faces.sortOn("pz", Array.NUMERIC | Array.DESCENDING);
	for (ind=0; ind < faces.length; ind++) {
		face_mc = faces[ind] as MovieClip;
		// if (faces[ind].pz < cube.z) {
		if (face_mc.pz < cube.z) {
			// cube.addChild(faces[ind]);
			face_mc.visible = true;
		} else {
			face_mc.visible = false;
		}
	}
}


----------------
 

SeeDa!!
Åê¹ÆNo.41298
投稿日時: 2009-1-23 15:45
職人
居住地: Nagoya
投稿: 221
使用環境:
WinXP
Flash CS4
au:W33SA?
Re: 3Dの立方体を正確に回転させるには
待ち遠しい限りです。
// さらに重くなると腕も鍛えられそう
引用:
Fumioさんは書きました:
Matrix3Dクラスは、Flash Player 10の実装ですので、収録には間に合いませんでした。具体的に日程は決まっていませんけど、つぎに改訂するときは解説に含め、行列の数学的な説明もかなり補うつもりです。


いえいえ、もう十分お腹いっぱいです。
visibleを使った方が軽くなるのは意外な気がします。
引用:
それだけでは何ですので、掲載いただいたスクリプトの関数rotationCube()に少しチューニングを加えてみました。実測はしていませんが、多少効率が上がっていると思います。
		// ザックリ略
		if (face_mc.pz < cube.z) {
			// cube.addChild(faces[ind]);
			face_mc.visible = true;
		} else {
			face_mc.visible = false;
		}
野中文雄
Åê¹ÆNo.41390
投稿日時: 2009-2-3 22:01
ちょんまげら
居住地: 東京
投稿: 4531
使用環境:
CS5.5 .6.8 Vista Home Premium (SP1)
Re: 3Dの立方体を正確に回転させるには
MAXのおまけネタに立方体の回転をつくったので、ご参考までに公開します。[ライブラリ]には100ピクセル四方の6枚のビットマップを納め、[クラス]としてImage0?Image5を設定しておきます。
// メインタイムライン: フレームアクション
var nX:Number = stage.stageWidth / 2;
var nY:Number = stage.stageHeight / 2;
var nSensitivity:Number = 0.2;
var nUnit:Number = 100 / 2;
var images_vector:Vector.<Array> = new Vector.<Array>();
var faces_vector:Vector.<Sprite> = new Vector.<Sprite>();
var cubeSprite:Sprite = new Sprite();
images_vector.push([Image0, new Vector3D(0, 0, -nUnit)]);
images_vector.push([Image1, new Vector3D(0, -nUnit, 0), ["rotationX", 90]]);
images_vector.push([Image2, new Vector3D(0, nUnit, 0), ["rotationX", -90]]);
images_vector.push([Image3, new Vector3D(nUnit, 0, 0), ["rotationY", 90]]);
images_vector.push([Image4, new Vector3D(-nUnit, 0, 0), ["rotationY", -90]]);
images_vector.push([Image5, new Vector3D(0, 0, nUnit), ["rotationX", 180]]);
initializeCube();
function initializeCube():void {
	var nLength:Number = images_vector.length;
	addChild(cubeSprite);
	cubeSprite.x = nX;
	cubeSprite.y = nY;
	cubeSprite.z = 0;
	for (var i:Number=0; i<nLength; ++i) {
		var my_array:Array = images_vector[i];
		var imageClass:Class = my_array[0] as Class;
		var myVector3D:Vector3D = my_array[1] as Vector3D;
		var rotation_array:Array = my_array[2] as Array;
		var mySprite:Sprite = new Sprite();
		var myBitmap:Bitmap = new Bitmap(new imageClass(0,0));
		faces_vector.push(mySprite);
		cubeSprite.addChild(mySprite);
		mySprite.addChild(myBitmap);
		myBitmap.x =  -  nUnit;
		myBitmap.y =  -  nUnit;
		mySprite.x = myVector3D.x;
		mySprite.y = myVector3D.y;
		mySprite.z = myVector3D.z;
		if (rotation_array) {
			mySprite[rotation_array[0]] = rotation_array[1];
		}
	}
	cubeSprite.addEventListener(Event.ENTER_FRAME, rotateCube);
}
function rotateCube(eventObject:Event):void {
	var nRotationX:Number =  -  (mouseY-nY) * nSensitivity;
	var nRotationY:Number = (mouseX-nX) * nSensitivity;
	rotateSprite(cubeSprite, nRotationX, nRotationY);
	arrangeFaces();
}
function rotateSprite(mySprite:Sprite, nRotationX:Number, nRotationY:Number):void {
	var myMatrix3D:Matrix3D = mySprite.transform.matrix3D;
	myMatrix3D.appendTranslation(-nX, -nY, 0);
	myMatrix3D.appendRotation(nRotationX, Vector3D.X_AXIS);
	myMatrix3D.appendRotation(nRotationY, Vector3D.Y_AXIS);
	myMatrix3D.appendTranslation(nX, nY, 0);
}
function arrangeFaces():void {
	var faces_array:Array = new Array();
	var faceSprite:Sprite;
	var nLastIndex:int = cubeSprite.numChildren - 1;
	var nLength:Number;
	var i:uint;
	nLength = faces_vector.length;
	for (i=0; i < nLength; ++i) {
		faceSprite = faces_vector[i];
		var nZ:Number = faceSprite.transform.getRelativeMatrix3D(this).position.z;
		if (nZ > cubeSprite.z) {
			faceSprite.visible = false;
		} else {
			faceSprite.visible = true;
			faces_array.push({face:faceSprite, z:-nZ});
		}
	}
	faces_array.sortOn("z", Array.NUMERIC);
	nLength = faces_array.length;
	for (i=0; i < nLength; ++i) {
		faceSprite = faces_array[i].face;
		cubeSprite.setChildIndex(faceSprite, nLastIndex);
	}
}


----------------
 

SeeDa!!
Åê¹ÆNo.41464
投稿日時: 2009-2-12 0:34
職人
居住地: Nagoya
投稿: 221
使用環境:
WinXP
Flash CS4
au:W33SA?
立方体だけでは面白くないから…
お椀を回してみました。
3Dの回転体(円掃体?)オブジェクトを作成する試みの派生です。
まだまだ効率の悪いスクリプトですが、赤字部分を修正すれば色んなものを回せます。(CS4限定..)
// メインタイムライン: フレームアクション

var nX:Number=stage.stageWidth/2;
var nY:Number=stage.stageHeight/2;
var nSensitivity:Number=0.2;
var nUnit:Number=100/2;
var lightV:Vector3D=new Vector3D(-200,150,0);

transform.perspectiveProjection.fieldOfView=55;

// 断面図の描画POINTを指定(2点以上)
var points:Array = new Array(
new Point(0, -110+50),
new Point(35, -86.8+50),
new Point(35, -110+50),
new Point(50.1, -110+50),
new Point(50.1, -86.8+50),
new Point(70.7, -70.7+50),
new Point(87, -49.9+50),
new Point(96.9, -25.7+50),
new Point(100, 0+50),
new Point(84.3, 0+50),
new Point(81.7, -21.6+50),
new Point(73.3, -42+50),
new Point(59.6, -59.6+50),
new Point(42.3, -73.2+50),
new Point(21.7, -81.7+50),
new Point(0, -84.3+50)
);

// 回転体の分割数(3以上)
var splitNum:uint=24;
var radian:Number=Math.PI*2/splitNum;

var owan:Sprite = new Sprite();
owan.x=stage.stageWidth/2;
owan.y=stage.stageHeight/2;
owan.z=0;

// splitNumで分割した回転体を描画する
var faces:Array = new Array();
for (var s:uint = 0; s < splitNum; s++) {
	var rotationAngle:Number=360/splitNum*s;
	var rotationRadian:Number=radian*s;
	for (var i:uint = 0; i < points.length-1; i++) {
		var trapezoid:MovieClip=drawTrapezoid(points[i],points[i+1],i);
		setRotate(trapezoid, rotationRadian);
		faces.push(trapezoid);
		owan.addChild(trapezoid);
	}
}

addChild(owan);
owan.addEventListener(Event.ENTER_FRAME, rotateObject);

// 深度調節といい加減な陰影表現
// 見えないスプライトも描画しちゃってます
function arrangeFaces():void {
	for (var i:uint = 0; i < faces.length; i++) {
		var nX:Number=faces[i].transform.getRelativeMatrix3D(root).position.x;
		var nY:Number=faces[i].transform.getRelativeMatrix3D(root).position.y;
		var nZ:Number=faces[i].transform.getRelativeMatrix3D(root).position.z;
		faces[i].nx=nX;
		faces[i].ny=nY;
		faces[i].nz=nZ;
		owan.removeChild(faces[i]);
	}
	faces.sortOn("nz", Array.NUMERIC | Array.DESCENDING);
	for (i = 0; i < faces.length; i++) {
		owan.addChild(faces[i]);
		// 光源との角度差を調べる
		var faseV:Vector3D=new Vector3D(faces[i].nx,faces[i].ny,faces[i].nz);
		var vAngle:Number=Vector3D.angleBetween(lightV,faseV);
		var offset:Number = (vAngle/Math.PI * 512 - 256) * 0.8;
		var color:ColorTransform=new ColorTransform(1,1,1,1,offset,offset,offset,0);
		faces[i].transform.colorTransform=color;
	}
}

// 回転体(owan)に配置するスプライトの回転位置調節
function setRotate(sprite:Sprite, myRadian:Number) {
	var distance:Number=Math.sqrt(Math.pow(sprite.x,2)+Math.pow(sprite.z,2));
	sprite.z=distance*Math.sin(myRadian);
	sprite.x=distance*Math.cos(myRadian);
	sprite.rotationY=- myRadian/Math.PI*180-90;
}

// 台形を描画する
function drawTrapezoid(pFrom:Point, pTo:Point, nCount:uint=0):MovieClip {
	var myColor:Number=nCount>7?0xff0000:0x000000;
	var _mc:MovieClip = new MovieClip();
	var apexes:Array=getTrapezoidApexes(pFrom,pTo);
	var nHeight:Number=Math.sqrt(Math.pow(apexes[0].y-apexes[1].y,2)+Math.pow(pFrom.y-pTo.y,2));
	_mc.graphics.beginFill(myColor, 1);
	_mc.graphics.moveTo(-apexes[0].x, -nHeight/2);
	_mc.graphics.lineTo( apexes[0].x, -nHeight/2);
	_mc.graphics.lineTo( apexes[1].x,  nHeight/2);
	_mc.graphics.lineTo(-apexes[1].x,  nHeight/2);
	_mc.graphics.lineTo(-apexes[0].x, -nHeight/2);
	_mc.graphics.endFill();
	_mc.rotationX=getSlantAngle(new Point(apexes[1].y,pTo.y),new Point(apexes[0].y,pFrom.y))-90;
	_mc.y = (pTo.y+pFrom.y)/2;
	_mc.z = -(apexes[1].y+apexes[0].y)/2;
	return _mc;
}

// 上面から見た台形の頂点座標を求める
function getTrapezoidApexes(upper:Point, bottom:Point):Array {
	var apexes:Array = new Array();
	var upperX:Number=upper.x*Math.sin(radian/2);
	var upperY:Number=upper.x*Math.cos(radian/2);
	apexes.push(new Point(upperX,upperY));
	var bottomX:Number=bottom.x*Math.sin(radian/2);
	var bottomY:Number=bottom.x*Math.cos(radian/2);
	apexes.push(new Point(bottomX,bottomY));
	return apexes;
}

// 傾斜角を求める
function getSlantAngle(pFrom:Point, pTo:Point):Number {
	var dx:Number=pFrom.x-pTo.x;
	var dy:Number=pFrom.y-pTo.y;
	return Math.atan2(dy, dx) * 180 / Math.PI;
}

// マウスに反応してオブジェクトを回転させる
function rotateObject(eventObject:Event):void {
	var nRotationX:Number = (mouseY-nY) * nSensitivity;
	var nRotationY:Number = (mouseX-nX) * nSensitivity;
	owan.transform.matrix3D.appendTranslation(- nX,- nY,0);
	owan.transform.matrix3D.appendRotation(nRotationY, Vector3D.Y_AXIS);
	owan.transform.matrix3D.appendRotation(nRotationX, Vector3D.X_AXIS);
	owan.transform.matrix3D.appendTranslation(nX,nY,0);
	arrangeFaces();
}

スクリプトの修正大歓迎します
SeeDa!!
Åê¹ÆNo.41469
投稿日時: 2009-2-12 21:01
職人
居住地: Nagoya
投稿: 221
使用環境:
WinXP
Flash CS4
au:W33SA?
Re: 立方体だけでは面白くないから…
も回してみました
押し出し(掃引体)は回転体に比べて簡単だと思っていたんですが、裏返ったものをきちんと消さないと正しく表示されません。
で、結局出来なかったから、、、Fを描いている正面と裏面の数値を偽装(x100)して誤魔化してます
(下記スクリプトは"F"です)

野中さんのご提示いただいたスクリプトのうち
引用:
Fumioさんは書きました:
var images_vector:Vector.<Array> = new Vector.<Array>();
var faces_vector:Vector.<Sprite> = new Vector.<Sprite>();
		var imageClass:Class = my_array[0] as Class;
		var myVector3D:Vector3D = my_array[1] as Vector3D;
		var rotation_array:Array = my_array[2] as Array;

あたりの知識がなくてチンプンカンプンですが、乗り越えないといけない壁なんだろうなぁ…

// メインタイムライン: フレームアクション
var point_array:Array = new Array(
new Point(-47,-70.8),
new Point(-15.8,-70.8),
new Point(47,-70.8),
new Point(47,-45),
new Point(-15.8,-45),
new Point(-15.8,-14.6),
new Point(25.9,-14.6),
new Point(25.9,11.7),
new Point(-15.8,11.7),
new Point(-15.8,70.7),
new Point(-47,70.7),
new Point(-47,11.7),
new Point(-47,-14.6),
new Point(-47,-45)
);
var nDepth:Number=90;

var pNum:uint=point_array.length;
var nX:Number = stage.stageWidth/2;
var nY:Number = stage.stageHeight/2;
var i:uint;
var faces:Array = new Array();
var nSensitivity:Number=0.1;
var lightV:Vector3D=new Vector3D(-200,150,0);

// 書き出すオブジェクトをステージのセンターに配置
var myObject:Sprite = new Sprite();
myObject.x = nX;
myObject.y = nY;
myObject.z = 0;

// 正面から見た図(上面/下面)を描画
var faceName:String = 'topFace';
var topFace:MovieClip = drawFace(faceName);
topFace.z = -nDepth/2;
faces.push(topFace);
myObject.addChild(topFace);

faceName = 'bottomFace';
var bottomFace:MovieClip = drawFace(faceName);
bottomFace.z = nDepth/2;
faces.push(bottomFace);
myObject.addChild(bottomFace);

// 側面(奥行き)を描画
for (i = 0; i < pNum; i++) {
	var pFrom:Point = point_array[i];
	var pTo:Point = i == pNum-1 ? point_array[0] : point_array[i+1];
	var mySprite:MovieClip = drawDepth(pFrom,pTo);
	faces.push(mySprite);
	myObject.addChild(mySprite);
}

// 深度調節
var faceNum:uint = faces.length;
addChild(myObject);
arrangeFaces();
myObject.addEventListener(Event.ENTER_FRAME, rotateObject);

// いい加減な深度調節といい加減な陰影表現
function arrangeFaces():void {
	var tempPoint:MovieClip;
	for (i = 0; i < faceNum; i++) {
		var nX:Number=faces[i].transform.getRelativeMatrix3D(root).position.x;
		var nY:Number=faces[i].transform.getRelativeMatrix3D(root).position.y;
		var nZ:Number=faces[i].transform.getRelativeMatrix3D(root).position.z;
		var faceName:String = faces[i].name;
		if (faceName == 'topFace' || faceName == 'bottomFace') nZ *= 100;
		faces[i].nx=nX;
		faces[i].ny=nY;
		faces[i].nz=nZ;
		myObject.removeChild(faces[i]);
	}
	var frontFlg:Boolean = true;
	faces.sortOn("nz", Array.NUMERIC | Array.DESCENDING);
	for (i = 0; i < faces.length; i++) {
		myObject.addChild(faces[i]);
		faces[i].visible = true;
		// 光源との角度差を調べる
		var faseV:Vector3D=new Vector3D(faces[i].nx,faces[i].ny,faces[i].nz);
		var vAngle:Number=Vector3D.angleBetween(lightV,faseV);
		var offset:Number = (vAngle/Math.PI * 512 - 300);
		var color:ColorTransform=new ColorTransform(1,1,1,1,offset,offset,offset,0);
		faces[i].transform.colorTransform=color;
	}
	
}

// 正面から見た図(上面/下面)を描画
function drawFace(faceName:String):MovieClip {
	var mySprite:MovieClip = new MovieClip();
	mySprite.graphics.beginFill(0xff0000);
	mySprite.graphics.moveTo(point_array[0].x, point_array[0].y);
	for (i=1; i < pNum; i++) {
		mySprite.graphics.lineTo(point_array[i].x, point_array[i].y);
	}
	mySprite.graphics.lineTo(point_array[0].x, point_array[0].y);
	mySprite.graphics.endFill();
	mySprite.name = faceName;
	return mySprite;
}
// 奥行きを描画
function drawDepth(pFrom:Point, pTo:Point):MovieClip {
	var mySprite:MovieClip = new MovieClip();
	var nCenter:Point = new Point((pFrom.x+pTo.x)/2, (pFrom.y+pTo.y)/2);
	var nDistance:Number = Point.distance(pFrom, pTo);
	var nRadian:Number = Math.atan2(pTo.y-pFrom.y,pTo.x-pFrom.x);
	var nDegree:Number = nRadian/Math.PI*180;
	mySprite.graphics.beginFill(0x999999);
	mySprite.graphics.moveTo(-nDistance/2, -nDepth/2);
	mySprite.graphics.lineTo(nDistance/2,  -nDepth/2);
	mySprite.graphics.lineTo(nDistance/2, nDepth/2);
	mySprite.graphics.lineTo(-nDistance/2, nDepth/2);
	mySprite.graphics.lineTo(-nDistance/2,  -nDepth/2);
	mySprite.graphics.endFill();
	mySprite.rotationX = 90;
	mySprite.rotationZ = nDegree;
	mySprite.x = nCenter.x;
	mySprite.y = nCenter.y;
	return mySprite;
}

// マウスに反応してオブジェクトを回転させる
function rotateObject(eventObject:Event):void {
	var nRotationX:Number = (mouseY-nY) * nSensitivity;
	var nRotationY:Number = -(mouseX-nX) * nSensitivity;
	myObject.transform.matrix3D.appendTranslation(- nX,- nY,0);
	myObject.transform.matrix3D.appendRotation(nRotationY, Vector3D.Y_AXIS);
	myObject.transform.matrix3D.appendRotation(nRotationX, Vector3D.X_AXIS);
	myObject.transform.matrix3D.appendTranslation(nX,nY,0);
	arrangeFaces();
}
SeeDa!!
Åê¹ÆNo.41477
投稿日時: 2009-2-16 6:00
職人
居住地: Nagoya
投稿: 221
使用環境:
WinXP
Flash CS4
au:W33SA?
Re: 立方体だけでは面白くないから…
球体を回してみた
これまで亜流でプリミティブもどきを作成してきましたが、UVマッピングを使いたかったので本流に挑戦してみました。

球体の上でクリックするとポリゴンラインの表示/非表示を切り替えられます。

フレームアクション
球体を配置して回転させる
var nX:Number = stage.stageWidth / 2;
var nY:Number = stage.stageHeight / 2;
var nSensitivity:Number = 0.1;

var myBall:DrawBall = new DrawBall(150, 30);
myBall.x = stage.stageWidth/2;
myBall.y = stage.stageHeight/2;
addChild(myBall);

addEventListener(Event.ENTER_FRAME, rotate);
function rotate(eventObject:Event):void{
	var nRotationX:Number = (mouseY-nX) * nSensitivity;
	var nRotationY:Number = -(mouseX-nY) * nSensitivity;
	myBall.myMatrix.appendRotation(nRotationX, Vector3D.X_AXIS);
	myBall.myMatrix.appendRotation(nRotationY, Vector3D.Y_AXIS);
	myBall.rendar();
}
addEventListener(MouseEvent.CLICK, frameView);
function frameView(eventObject:MouseEvent):void{
	myBall.wireFlg*=-1;
}


クラス
球体を描く
package {
	import flash.display.*;
	import flash.geom.*;
	public class DrawBall extends Sprite {
		
		private var radius:Number;
		private var split:uint;
		private var vApexes    :Vector.<Number> = new Vector.<Number>();
		private var vFlatApexes:Vector.<Number> = new Vector.<Number>();
		private var vIndices   :Vector.<int>    = new Vector.<int>();
		private var vUVT       :Vector.<Number> = new Vector.<Number>();
		private var myBitmap   :mappingdata = new mappingdata(0,0);
		private var mySpace    :Sprite = new Sprite();
		public  var myMatrix   :Matrix3D;
		public  var wireFlg    :int = 1;
		public function DrawBall(radius:Number=100, split:uint=10):void {
			myMatrix = new Matrix3D();
			myMatrix.appendRotation(60,Vector3D.X_AXIS);
			myMatrix.appendRotation(20,Vector3D.Y_AXIS);
			addChild(mySpace);
			setApexes(radius, split);
			setIndices(split);
			rendar();
		}
		private function setApexes(nRadius:Number, nSplit:uint):void {
			for (var v:uint = 0; v <= nSplit; v++) {
				if (v % 2 == 0) {
					var radianV:Number = Math.PI * v / nSplit;
					var nDist  :Number = nRadius * Math.sin(radianV);
					var nY     :Number = nRadius * Math.cos(radianV);
					for (var h:uint = 0; h <= nSplit; h++) {
						var radianH:Number = Math.PI * 2 * h / nSplit;
						var nX:Number = nDist * Math.cos(radianH);
						var nZ:Number = nDist * Math.sin(radianH);
						vApexes.push(nX, nY, nZ);
						vUVT.push(h/nSplit,v/nSplit,0);
					}
				}
			}
		}
		private function setIndices(nSplit:uint) {
			for (var v:uint = 0; v < nSplit; v++) {
				for (var h:uint = 0; h < nSplit; h++) {
					var nP = (nSplit+1) * v + h;
					var i0:uint = nP;
					var i1:uint = nP+1;
					var i2:uint = nP+nSplit+1;
					var i3:uint = nP+nSplit+2;
					vIndices.push(i0,i1,i2, i3,i2,i1);
				}
			}
		}
		public function rendar() {
			Utils3D.projectVectors(myMatrix, vApexes, vFlatApexes, vUVT);
			mySpace.graphics.clear();
			mySpace.graphics.beginBitmapFill(myBitmap);
			if (wireFlg == 1) {
				mySpace.graphics.lineStyle(1,0x000000);
			}
			mySpace.graphics.drawTriangles(vFlatApexes, vIndices, vUVT, TriangleCulling.POSITIVE);
			mySpace.graphics.endFill();
		}
	}
}


スレッド表示 | 新しいものから 前のトピック | 次のトピック | トップ

投稿するにはまず登録を
 
Copyright (C) 2003 FLASH-japan. All rights reserved.
Powered by Xoops