ログイン
メインメニュー
|
投稿者 |
スレッド |
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();
}
}
}
|
|
|
|
|