forked from: Ribbon?
行列でやってみた
// forked from HaraMakoto's Ribbon?
// 行列でやってみた
package
{
import flash.display.Sprite;
import flash.events.Event;
import org.papervision3d.cameras.Camera3D;
import org.papervision3d.materials.ColorMaterial;
import org.papervision3d.materials.WireframeMaterial;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.objects.primitives.Sphere;
import org.papervision3d.render.BasicRenderEngine;
import org.papervision3d.render.QuadrantRenderEngine;
import org.papervision3d.scenes.Scene3D;
import org.papervision3d.view.Viewport3D;
import org.papervision3d.objects.primitives.Plane;
[SWF(width="465", height="465", backgroundColor="0x000000", frameRate="40")]
public class RibbonRotate extends Sprite
{
/**
* 3Dベース系の定義
*/
private var scene:Scene3D;
private var viewport:Viewport3D; //3Dアイテムを入れる箱
private var renderer:BasicRenderEngine; //レンダラー
public var camera:Camera3D; //カメラオブジェクト
private var container:DisplayObject3D;
private var camTarget:DisplayObject3D; //カメラターゲット
/**
* 3Dオブジェクトの定義
*/
private var pEx:PlaneExt; //頭
private var p2Ex:PlaneExt; //しっぽの頭
private var pExArray:Array = new Array(); //PlaneChilds入れる配列
public function RibbonRotate()
{
if (stage) _addStage();
else addEventListener(Event.ADDED_TO_STAGE, _addStage);
}
private function _addStage(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, _addStage);
paperDisplaySetting();
setSphere();
setPlanes();
addEventListener( Event.ENTER_FRAME, _onEnterFrame ); //毎フレーム処理
}
private function setPlanes():void
{
//マテリアル
var CM:ColorMaterial = new ColorMaterial(0xFCFCFC,1);
CM.doubleSided = true;
CM.oneSide = false;
//頭
pEx = new PlaneExt(CM,5,10);
container.addChild( pEx );
//しっぽの頭
p2Ex = new PlaneExt(CM,5,10);
p2Ex.setTargetPL( pEx );
container.addChild( p2Ex );
pExArray.push( p2Ex );
//しっぽ
for( var i:int=1;i<60; i++ )
{
var ppEx:PlaneExt = new PlaneExt(CM,5,10);
ppEx.setTargetPL( pExArray[i-1] );
container.addChild( ppEx );
pExArray.push( ppEx );
}
}
/**
* 3Dフィールド設定
*/
private function paperDisplaySetting():void
{
//ビューポート設定
viewport = new Viewport3D(640,480,true);
addChild( viewport );
//カメラ設定
camera = new Camera3D();
camera.z = -300;
camera.focus = 500;
camera.zoom = 1;
//カメラターゲット設定
camTarget = new DisplayObject3D();
camera.target = camTarget;
camTarget.x = camTarget.y = camTarget.z = 0;
//シーン設定
scene = new Scene3D;
//ベース設定
container = new DisplayObject3D();
container.x = container.y = container.z = 0;
scene.addChild( container );
//レンダー設定
renderer = new BasicRenderEngine();
}
/**
* 球体配置
*/
private function setSphere():void
{
var _bigSphere:Sphere = new Sphere( new WireframeMaterial(0x666666, 10),20 );
_bigSphere.useOwnContainer = true;
container.addChild( _bigSphere );
}
/**
* 毎フレーム処理
*/
private function _onEnterFrame( e:Event ):void
{
RenderingScene();
}
/**
* レンダリング
*/
private function RenderingScene():void
{
if( mouseX > 0 && mouseX < stage.stageWidth && mouseY > 0 && mouseY < stage.stageHeight )
{
var vx:Number = 0;
vx += 0.1 * ( viewport.containerSprite.mouseX * 0.1 - vx );
container.rotationY += vx;
container.rotationX += 0.5 * ( viewport.containerSprite.mouseY * 0.4 - container.rotationX );
}
pEx._onEnterFrame(null);
var arrNum:Number = pExArray.length;
for( var i:int=0; i < arrNum; i++ )
{
pExArray[i]._onEnterFrame_child(null);
}
//レンダリング
renderer.renderScene(scene,camera,viewport);
}
}
}
import flash.events.Event;
import org.papervision3d.core.geom.renderables.Vertex3D;
import org.papervision3d.core.math.Matrix3D;
import org.papervision3d.core.math.Number3D;
import org.papervision3d.core.math.Quaternion;
import org.papervision3d.core.proto.MaterialObject3D;
import org.papervision3d.objects.primitives.Plane;
import org.papervision3d.objects.primitives.Sphere;
class PlaneExt extends Plane
{
public var vx:Number=0;
public var vy:Number=0;
public var vz:Number=0;
public var rx:Number;
public var ry:Number;
public var fx:Number=0;
public var fy:Number=0;
public var fz:Number=0;
private var xLimit:Number = 100;
private var yLimit:Number = 100;
private var zLimit:Number = 100;
public var ox:Number = 0;
public var oy:Number = 0;
public var oz:Number = 0;
public var ovx:Number = 0;
public var ovy:Number = 0;
public var ovz:Number = 0;
private var toRadian:Number = Math.PI/180;
private var targetPlane:PlaneExt;
public function PlaneExt( material:MaterialObject3D=null, width:Number=0, height:Number=0, segmentsW:Number=0, segmentsH:Number=0 )
{
super( material, width, height, segmentsW, segmentsH);
rx = 360 * Math.random();
ry = 360 * Math.random();
//Planeの原点を移動
for each(var obj_vartices:Vertex3D in this.geometry.vertices)
{
obj_vartices.y -= 5;
}
}
public function setTargetPL(pl:PlaneExt):void
{
targetPlane = pl;
}
public function _onEnterFrame(e:Event):void
{
ox = fx;
oy = fy;
oz = fz;
ovx = vx;
ovy = vy;
ovz = vz;
rx += 10;
vx = 8 * Math.cos(rx * toRadian);
vy = 8 * Math.sin(rx * toRadian);
vz = 8 * Math.cos(ry * toRadian);
fx += vx;
fy += vy;
fz += vz;
if(fx > xLimit){rx = rx + 90;}
if(fx < -xLimit){rx = rx + 90;}
if(fy > yLimit){rx = rx + 90;}
if(fy < -yLimit){rx = rx + 90;}
if(fz > zLimit){ry = ry + 90;}
if(fz < -zLimit){ry = ry + 90;}
setAttitude();
this.x = fx;
this.y = fy;
this.z = fz;
}
public function _onEnterFrame_child(e:Event):void
{
ox = fx;
oy = fy;
oz = fz;
ovx = vx;
ovy = vy;
ovz = vz;
fx = targetPlane.ox;
fy = targetPlane.oy;
fz = targetPlane.oz;
vx = targetPlane.ovx;
vy = targetPlane.ovy;
vz = targetPlane.ovz;
setAttitude();
this.x = fx;
this.y = fy;
this.z = fz;
}
public function setAttitude():void
{
//ある方向に向けたい軸
var StartVec:Number3D = new Number3D( this.transform.n12, this.transform.n22, this.transform.n32 );
//目標になる座標
var TargetPoint:Number3D = new Number3D( this.vx, this.vy, this.vz );
//元のベクトルを揃わせたい最終的なベクトル
var EndVec:Number3D = Number3D.add( StartVec, TargetPoint );
StartVec.normalize();
EndVec.normalize();
//2つのベクトルの法線ベクトル(回転軸)
var vcross:Number3D = Number3D.cross( EndVec, StartVec );
vcross.normalize();
//2つのベクトルから回転角度(ラジアン)算出
var rot:Number = Math.acos(Number3D.dot( StartVec, EndVec));
//ベクトルを合わせるための回転軸と回転角から回転行列作成
var mat:Matrix3D = Matrix3D.rotationMatrix(vcross.x, vcross.y, vcross.z, rot);
//行列を適用
this.transform = Matrix3D.multiply3x3(mat, this.transform);
}
}