DisplayObject3D.lookAt()をQuaternion使って実装
/**
* Copyright uwi ( http://wonderfl.net/user/uwi )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/vqj6
*/
package {
import flash.display.Sprite;
import flash.events.Event;
import org.papervision3d.view.BasicView;
import org.papervision3d.objects.special.*;
import org.papervision3d.materials.special.*;
import org.papervision3d.objects.DisplayObject3D;
import org.papervision3d.core.math.*;
import flash.text.*;
[SWF(backgroundColor="0x000000", frameRate="60")]
public class FlashTest extends BasicView {
private var _up : Number3D;
private var _front : Number3D;
private var _targ : Number3D;
private var _tf : TextField;
public function FlashTest() {
super(0, 0, true, false);
_tf = new TextField();
addChild(_tf);
_tf.textColor = 0xffffff;
_tf.width = 465;
_tf.height = 100;
var pf : ParticleField = new ParticleField(
new ParticleMaterial(0xffffff, 10, ParticleMaterial.SHAPE_SQUARE),
500,
1,
200, 200, 200);
scene.addChild(pf);
camera.z = -70;
_up = new Number3D(0, 1, 0);
_front = new Number3D(0, 0, 1);
setTarg();
startRendering();
}
private function setTarg() : void
{
// 目標視線ベクトルを決める
var t : Number = Math.random() * Math.PI * 2;
var u : Number = Math.random() * Math.PI;
_targ = new Number3D(
Math.cos(t) * Math.cos(u),
Math.sin(t) * Math.cos(u),
Math.sin(u)
);
// 差をとって回転用クォータニオンを生成
var n : Number3D = Number3D.cross(_front, _targ);
n.normalize();
var angle : Number = Math.acos(Number3D.dot(_front, _targ));
_q = Quaternion.createFromAxisAngle(n.x, n.y, n.z, 0.01);
_qc = Quaternion.conjugate(_q);
}
private var _q : Quaternion;
private var _qc : Quaternion;
// クォータニオンのベクトルへの適用
private function applyQuaternion(src : Number3D, q : Quaternion, qc : Quaternion) : Number3D
{
var qSrc : Quaternion = new Quaternion(src.x, src.y, src.z, 0);
var qDst : Quaternion = Quaternion.multiply(qc, qSrc);
qDst = Quaternion.multiply(qDst, q);
return new Number3D(qDst.x, qDst.y, qDst.z);
}
override protected function onRenderTick(e : Event = null) : void
{
// _tf.text = "" + _q + "\n" + camera.scaleZ;
// 視線とカメラの上のベクトルを回転
_front = applyQuaternion(_front, _q, _qc);
_up = applyQuaternion(_up, _q, _qc);
// 行列をつくってカメラに適用
var xAxis : Number3D = Number3D.cross(_front, _up);
xAxis.normalize();
var look : Matrix3D = new Matrix3D();
look.n11 = xAxis.x * camera.scaleX;
look.n21 = xAxis.y * camera.scaleX;
look.n31 = xAxis.z * camera.scaleX;
look.n12 = -_up.x * camera.scaleY;
look.n22 = -_up.y * camera.scaleY;
look.n32 = -_up.z * camera.scaleY;
look.n13 = _front.x * camera.scaleZ;
look.n23 = _front.y * camera.scaleZ;
look.n33 = _front.z * camera.scaleZ;
camera.copyTransform(look);
// 方向転換
if(Number3D.dot(_front, _targ) < 0.03){
setTarg();
}
super.onRenderTick(e);
}
}
}