2008-03-05 | 21:14
マウスドラッグでポイント移動できます。
クォータニオンのslerp(球面線形補間)でベジエカーブを求めています。
クォータニオンのslerp(球面線形補間)でベジエカーブを求めています。
package{ import flash.display.*; import flash.events.*; import flash.geom.*; import flash.utils.*; import flash.filters.DropShadowFilter; import org.papervision3d.core.math.*; [SWF(width="600", height="400",backgroundColor="0xffffff")] public class BezierWithQuaternion extends Sprite{ private var balls:Array = []; private var RADIUS:int = 6; public function BezierWithQuaternion(){ var points:Array = [ {x:100,y:320}, {x:200,y:200}, {x:300, y:200}, {x:400,y:320}]; for(var i:int = 0 ; i < points.length ; i++){ var b:Ball = new Ball(0xff0000, RADIUS); balls.push(b); addChild(b); b.x = points[i].x; b.y = points[i].y; b.addEventListener( MouseEvent.MOUSE_DOWN, pickup ); b.addEventListener( MouseEvent.MOUSE_UP, place ); b.addEventListener( MouseEvent.MOUSE_MOVE, function(e:*):void{ cal(); }); } cal(); } public function pickup( event:MouseEvent ):void { // ドラッグ処理を開始して、影フィルターをつける event.target.startDrag( ); event.target.filters = [ new DropShadowFilter( ) ]; // 最前面に表示されるようにする setChildIndex( DisplayObject( event.target ), numChildren - 1 ); } public function place( event:MouseEvent ):void { // ドラッグ処理を終了して影フィルターをオフ event.target.stopDrag( ); event.target.filters = null; cal(); } private function cal() :void{ graphics.clear(); var quaternions:Array = []; for each(var ball:Ball in balls) { quaternions.push(new Quaternion(ball.x, ball.y, 0)); } graphics.lineStyle(3,0xff, 0.7); graphics.moveTo(balls[0].x, balls[0].y); var nq0:Quaternion = quaternions[0]; var nq1:Quaternion = quaternions[1]; var nq2:Quaternion = quaternions[2]; var nq3:Quaternion = quaternions[3]; for(var t:Number = 0 ; t <= 1.0 ; t += 0.01){ var qc:Quaternion = curve(nq0, nq1, nq2, nq3, t); graphics.lineTo(qc.x , qc.y ); } graphics.lineTo(balls[3].x, balls[3].y); } private function curve(q00:Quaternion, q01:Quaternion, q02:Quaternion, q03:Quaternion, t:Number):Quaternion{ var q10:Quaternion = slerp(q00, q01, t); var q11:Quaternion = slerp(q01, q02, t); var q12:Quaternion = slerp(q02, q03, t); var q20:Quaternion = slerp(q10, q11, t); var q21:Quaternion = slerp(q11, q12, t); return slerp(q20, q21, t); } private function slerp(q1:Quaternion, q2:Quaternion, t:Number):Quaternion{ var nq1:Quaternion = new Quaternion(q1.x, q1.y, q1.z, q1.w); var nq2:Quaternion = new Quaternion(q2.x, q2.y, q2.z, q2.w); nq1.normalize(); nq2.normalize(); var dot:Number = Quaternion.dot(nq1,nq2); var angle:Number = Math.acos(dot); if(isNaN(angle) || Math.abs(dot) >= 1.0 || angle == 0){ return new Quaternion(q1.x, q1.y, q1.z, q1.w); } var t1:Number = Math.sin((1-t)*angle) / Math.sin(angle); var t2:Number = Math.sin(t*angle) / Math.sin(angle); var q:Quaternion = new Quaternion(t1*q1.x + t2*q2.x, t1*q1.y + t2*q2.y, t1*q1.z + t2*q2.z, t1*q1.w + t2*q2.w); return q; } } } import flash.display.*; internal class Ball extends Sprite{ public function Ball(color:int, radius:int){ graphics.beginFill(color); graphics.drawCircle(0,0,radius); graphics.endFill(); } }
スポンサーサイト