// 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); } } forked from: Ribbon?