追尾カメラ uwi forked:6favorite:29lines:290license : MIT License modified : 2010-01-20 01:03:06 Embed Tweet package { import org.papervision3d.view.BasicView; import flash.text.TextField; import flash.events.Event; import flash.events.MouseEvent; import net.hires.debug.Stats; import org.papervision3d.objects.primitives.*; import org.papervision3d.objects.*; import org.papervision3d.core.math.*; import org.papervision3d.core.proto.*; import org.papervision3d.materials.*; import org.papervision3d.materials.special.*; import org.papervision3d.objects.special.*; import com.bit101.components.*; [SWF(backgroundColor="0x000000", frameRate="60")] public class PV3D extends BasicView { private var _tf : TextField; private var _pp : PaperPlane; private var _XX : Number; private var _YY : Number; private var _ZZ : Number; private var _t : Number; private var _next : DisplayObject3D; private var _ppup : Number3D; private var _prevDir : Number3D = null; private var _cameras : Array; public function PV3D() { super(0, 0, true, false); graphics.beginFill(0x000000); graphics.drawRect(0, 0, 465, 465); graphics.endFill(); scene.addChild(new ParticleField(new ParticleMaterial(0xffff99, 0.8, 0), 3000, 2, 1300, 1300, 1300)); var wm : MaterialObject3D = new WireframeMaterial(0xffffff, 0.5); wm.oneSide = false; _pp = new PaperPlane(wm); scene.addChild(_pp); _XX = 1 + Math.random(); _YY = 1 + Math.random(); _ZZ = 1 + Math.random(); _t = Math.random() * 100; _next = new DisplayObject3D(); // カメラ _cameras = []; var tc : TrackingCamera = new TrackingCamera(_pp, new Number3D(0, 1, 0)); tc.x = 0; tc.y = 0; tc.z = 0; _cameras.push(tc); var rc : RidingCamera = new RidingCamera(_pp, new Number3D(0, 1, 0)); _cameras.push(rc); var sc : SphereCamera = new SphereCamera(new Number3D(0, 0, 0), 1000, new Number3D(0, 0, 1), new Number3D(0, 1, 0)); _cameras.push(sc); _ppup = null; _tf = new TextField(); addChild(_tf); _tf.textColor = 0xffffff; _tf.width = 100; _tf.height = 465; // addChild(new Stats()); _modeCamera = -1; changeMode(); startRendering(); var btn : PushButton = new PushButton(this, 365, 0, "change", function(e : MouseEvent) : void { changeMode(); }); stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); } private var _modeCamera : int; private function changeMode() : void { _modeCamera = (_modeCamera + 1) % _cameras.length; _camera = _cameras[_modeCamera]; _tf.text = ["TrackingCamera", "RidingCamera", "SphereCamera"][_modeCamera]; } private var _prevX : Number = 0; private var _prevY : Number = 0; private function onMouseMove(e : MouseEvent) : void { if(!(_camera is SphereCamera))return; if(e.buttonDown){ // ボタンをおしている状態のときのみカメラを移動 if(_prevX != 0 && _prevY != 0){ var sc : SphereCamera = SphereCamera(_camera); // 直前との差分だけ移動 sc.move((stage.mouseX - _prevX) * 0.005, (stage.mouseY - _prevY) * 0.005); } _prevX = stage.mouseX; _prevY = stage.mouseY; }else{ _prevX = 0; _prevY = 0; } } override protected function onRenderTick(e : Event = null) : void { _pp.x = 500 * Math.cos(_XX * _t); _pp.y = 500 * Math.cos(_YY * _t); _pp.z = 500 * Math.cos(_ZZ * _t); _next.x = 500 * Math.cos(_XX * (_t + 0.01)); _next.y = 500 * Math.cos(_YY * (_t + 0.01)); _next.z = 500 * Math.cos(_ZZ * (_t + 0.01)); var curDir : Number3D = Number3D.sub(_next.position, _pp.position); curDir.normalize(); if(_ppup == null){ var x : Number3D = Number3D.cross(new Number3D(0, 1, 0), curDir); x.normalize(); _ppup = Number3D.cross(x, curDir); } if(_prevDir != null){ // 飛行機ヨー用 var X : Number3D = Number3D.cross(_prevDir, _ppup); var dx : Number = Number3D.dot(curDir, X) / X.moduloSquared; var n : Number3D = Number3D.cross(_prevDir, curDir); // if(n.moduloSquared > 0.00000001){ if(n.moduloSquared != 0){ n.normalize(); var angle : Number = Math.acos(Number3D.dot(_prevDir, curDir)); _ppup = QCamera3D.applyQuaternion([_ppup], n, angle)[0]; } var airup : Number3D = QCamera3D.applyQuaternion([_ppup], curDir, dx*10)[0]; _pp.lookAt(_next, airup); }else{ _pp.lookAt(_next, _ppup); } _prevDir = curDir; TrackingCamera(_cameras[0]).track(); // 3frameほど調整しないといけない if(ttt < 3){ RidingCamera(_cameras[1])._up = _ppup.clone(); ttt++; } RidingCamera(_cameras[1]).move(60, 230); _t += 0.01; super.onRenderTick(e); } private var ttt : uint = 0; private function tr(...o : Array) : void { _tf.appendText(o + "\n"); _tf.scrollV = _tf.maxScrollV; } } } import org.papervision3d.core.math.*; import org.papervision3d.objects.*; import org.papervision3d.cameras.*; // ジンバルロックを解消した以外はCamera3Dと同じ class QCamera3D extends Camera3D { public var _up : Number3D; // カメラの上の向きの単位ベクトル protected var _front : Number3D; private var _prevDir : Number3D; private var _ltarg : DisplayObject3D; public function QCamera3D(up : Number3D, front : Number3D = null) { super(); _up = null; _ltarg = new DisplayObject3D(); init(up, front); } // prevDirからcurDirへ向ける回転を_upにかけるだけ。カメラ自体に操作はしない public function rotate(curDir : Number3D) : void { if(_prevDir != null){ var n : Number3D = Number3D.cross(_prevDir, curDir); // if(n.moduloSquared > 0.00000001){ if(n.moduloSquared != 0){ n.normalize(); var angle : Number = Math.acos(Number3D.dot(_prevDir, curDir)); if(_front != null){ var a : Array = applyQuaternion([_front, _up], n, angle); _front = a[0]; _up = a[1]; }else{ _up = applyQuaternion([_up], n, angle)[0]; } } _prevDir.copyFrom(curDir); }else{ _prevDir = curDir.clone(); } } // カメラの右方向へx[rad], 上方向へy[rad]回転させる public function rotateXY(x : Number, y : Number) : void { if(_front == null)return; // X方向の移動 _front = applyQuaternion([_front], _up, -x)[0]; // Y方向の移動 var right : Number3D = Number3D.cross(_up, _front); right.normalize(); var ret : Array = applyQuaternion([_front, _up], right, y); _front = ret[0]; _up = ret[1]; } public function head() : void { if(_front != null){ // まわりくどい var ltpos : Number3D = this.position.clone(); ltpos.plusEq(_front); _ltarg.position = ltpos; this.lookAt(_ltarg, _up); } } public function init(up : Number3D = null, front : Number3D = null) : void { if(up != null){ _up = up.clone(); _up.normalize(); } if(front != null){ _front = front.clone(); _front.normalize(); }else{ _front = null; } _prevDir = null; } // axisを軸にangle回転させる変換を、srcsの要素それぞれに適用する public static function applyQuaternion(srcs : Array, axis : Number3D, angle : Number) : Array { var q : Quaternion = Quaternion.createFromAxisAngle( axis.x / axis.modulo, axis.y / axis.modulo, axis.z / axis.modulo, angle ); var qc : Quaternion = Quaternion.conjugate(q); var ret : Array = []; for each(var src : Number3D in srcs){ var qSrc : Quaternion = new Quaternion(src.x, src.y, src.z, 0); var qDst : Quaternion = Quaternion.multiply(qc, qSrc); qDst.mult(q); ret.push(new Number3D(qDst.x, qDst.y, qDst.z)); } return ret; } } // 球面上を動き、球の中心を見るカメラ class SphereCamera extends QCamera3D { private var _O : DisplayObject3D; // 球の中心 private var _R : Number; // 球の半径 public function SphereCamera(O : Number3D, R : Number, front : Number3D, up : Number3D) : void { super(up, front); _O = new DisplayObject3D(); _O.x = O.x; _O.y = O.y; _O.z = O.z; _R = R; move(); } public function move(x : Number = 0, y : Number = 0) : void { rotateXY(x, y); this.x = _front.x * -_R + _O.x; this.y = _front.y * -_R + _O.y; this.z = _front.z * -_R + _O.z; this.lookAt(_O, _up); } } // 固定視点から継続的にターゲッティングするカメラ class TrackingCamera extends QCamera3D { private var _targ : DisplayObject3D; public function TrackingCamera(targ : DisplayObject3D, up : Number3D) { super(up); _targ = targ; } public function track() : void { var curDir : Number3D = Number3D.sub(_targ.position, this.position); curDir.normalize(); rotate(curDir); this.lookAt(_targ, _up); } } // ゲットライド! class RidingCamera extends QCamera3D { private var _ride : DisplayObject3D; private var _prevPos : Number3D; public function RidingCamera(ride : DisplayObject3D, up : Number3D, front : Number3D = null) { super(up, front); _ride = ride; _prevPos = _ride.position.clone(); } public function move(up : Number = 0, back : Number = 0) : void { var curDir : Number3D = Number3D.sub(_ride.position, _prevPos); curDir.normalize(); if(_front == null){ _front = curDir.clone(); } rotate(curDir); var curPos : Number3D = _ride.position.clone(); var temp : Number3D; temp = _up.clone(); temp.multiplyEq(up); curPos.plusEq(temp); temp = _front.clone(); temp.multiplyEq(-back); curPos.plusEq(temp); this.position = curPos; head(); _prevPos.copyFrom(_ride.position); } } Code Fullscreen Preview Fullscreen bradsedito NINECUBE tjoen entermeister.. zawa digitrick djankey namagome ninehundred y_tti nanlow osamX Kevin_Yin 178ep3 dizgid flasher_bbb matsumos Nyarineko matsu4512 yamat Nicolas paq qwertyui : Universe Hyac_Meg : なるほど~♪ toruu_mw : こういう3Dが作りたい。 a440hlz : 3Dbeautifl OKASUKE : Papervision3d気持ちいい JohnBrookes : camera3DextendPV3D clockmaker : Papervision3Dpv3d 3D Papervision3D Universe beautifl camera3D extend pv3d Number3D angle Number3D.cross Quaternion rotate Number3D.sub modulo Number3D.dot dx multiplyEq clone Math.acos beginFill endFill copyFrom drawRect moduloSquared mouseX mouseY Math.cos sort new page view favorite forked pv0 forked from: 追尾カメラ Joe.Brant forked:0 favorite:0lines:290 (diff:1) pv145 forked from: 追尾カメラ bradsedito forked:1 favorite:0lines:290 (diff:1) pv101 forked from: 追尾カメラ smallflowergame forked:0 favorite:0lines:290 (diff:1) pv157 forked from: 追尾カメラ hbhmao forked:1 favorite:0lines:290 (diff:1) pv149 forked from: 追尾カメラ hbhmao forked:0 favorite:0lines:290 (diff:1) pv804 forked from: 追尾カメラ uwi forked:0 favorite:8lines:353 (diff:258) tag: 3D Camera3D Papervision3D camera 視点