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()
{
addEventListener( Event.ADDED_TO_STAGE, _addStage );
}
private function _addStage(e:Event):void
{
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,10,5);
container.addChild( pEx );
//しっぽの頭
p2Ex = new PlaneExt(CM,10,5);
p2Ex.setTargetPL( pEx );
container.addChild( p2Ex );
pExArray.push( p2Ex );
//しっぽ
for( var i:uint=1; i<60; i++ )
{
var ppEx:PlaneExt = new PlaneExt(CM,10,5);
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 QuadrantRenderEngine(QuadrantRenderEngine.ALL_FILTERS);
}
/**
* 球体配置
*/
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 );
}
objectsMove();
//レンダリング
renderer.renderScene(scene,camera,viewport);
}
public function objectsMove():void{
pEx._onEnterFrame(null);
var arrNum:Number = pExArray.length;
for( var i:uint=0; i<arrNum; i++ )
{
pExArray[i]._onEnterFrame_child(null);
}
}
}
}
import flash.events.Event;
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;
private var ptSphere:Sphere;
private var Mtx1:Matrix3D;
private var planeQuat:Quaternion = new Quaternion();
private var slerpQuat:Quaternion = new Quaternion();
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;
public var posArray:Array = new Array(); //位置を記録する配列
private var posNum:uint = 5;
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);
posArray.push( { x:0, y:0, z:0, vx:0, vy:0, vz:0} );
rx = 360 * Math.random();
ry = 360 * Math.random();
Mtx1 = Matrix3D.clone(this.transform);
planeQuat = Quaternion.createFromMatrix(this.transform);
}
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;
posArray.push( { x:ox, y:oy, z:ox, vx:ovx, vy:ovy, vz:ovz} );
if(posArray.length > posNum) posArray.shift(); //配列が一定数を超えたら一番古いものを捨てる。
rx += 10;
vx = 8 * Math.cos(rx * Math.PI/180);
vy = 8 * Math.sin(rx * Math.PI/180);
vz = 8 * Math.cos(ry * Math.PI/180);
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;}
setQuatanion();
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;
var poslength:uint = targetPlane.posArray[poslength].length-1;
fx = targetPlane.ox;
fy = targetPlane.oy;
fz = targetPlane.oz;
vx = targetPlane.ovx;
vy = targetPlane.ovy;
vz = targetPlane.ovz;
setQuatanion();
this.x = fx;
this.y = fy;
this.z = fz;
}
public function setQuatanion():void
{
//回転させたい点の初期位置(始点)のクォータニオン生成
var qStart:Quaternion = new Quaternion(20, 0, 0 ,0);
//終点
var EndVec:Number3D = new Number3D( vx, vy, vz );
//開始点(てきとうに)
var StartVec:Number3D = new Number3D( 20, 0, 0 );
EndVec.normalize();
StartVec.normalize();
//法線ベクトル(回転軸)
var vcross:Number3D = Number3D.cross(StartVec, EndVec);
//始点と終点のベクトルから回転角度(ラジアン)生成
var rot:Number = Math.acos(Number3D.dot(StartVec, EndVec));
//指定軸まわりの回転クォータニオン生成
var q:Quaternion = Quaternion.createFromAxisAngle(vcross.x,vcross.y,vcross.z,rot);
//qの共役クォータニオン
var r:Quaternion = Quaternion.conjugate(q);
//クォータニオンから行列に変換
var rotMtx:Matrix3D = Matrix3D.quaternion2matrix(r.x,r.y,r.z,r.w,rotMtx);
var m:Matrix3D = Matrix3D.multiply(rotMtx,Mtx1);
slerpQuat = Quaternion.slerp(planeQuat, r, 1);
this.copyTransform(slerpQuat.matrix);
}
}