In case Flash no longer exists; a copy of this site is included in the Flashpoint archive's "ultimate" collection.

Dead Code Preservation :: Archived AS3 works from wonderfl.net

平面に描いた線を3D化(表もあれば裏もある)

マウスで引いた線を立体にする
* マウスを押して動かしている間線を描いて
* マウスを離したら3D化
*----------------------------------------
* 交点を検出して表示します。
* Special Thanks uwiさん
*----------------------------------------
* ToDo 陰影をつける
*      3D描画時に交点情報を入れる
*      透視投影にする
*      余分な頂点を割愛する
*      etc. etc...
/**
 * Copyright Kay ( http://wonderfl.net/user/Kay )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/7fEM
 */

// forked from Kay's 平面に描いた線を3D化(暫定Ver)
// forked from Kay's ドラッグして描いた線の交差判定 
// forked from Kay's Basic お絵かき
/*
 * マウスで引いた線を立体にする
 * マウスを押して動かしている間線を描いて
 * マウスを離したら3D化
 *----------------------------------------
 * 交点を検出して表示します。
 * Special Thanks uwiさん
 *----------------------------------------
 * ToDo 陰影をつける
 *      3D描画時に交点情報を入れる
 *      透視投影にする
 *      余分な頂点を割愛する
 *      etc. etc...
 */

package {
	
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import flash.events.Event;
    import flash.text.TextField;
    import flash.geom.Point;
    import flash.geom.Matrix3D;
    import flash.geom.Utils3D;
    import flash.geom.Vector3D;
    import flash.display.TriangleCulling;
    import flash.geom.PerspectiveProjection;
    
    [SWF(width=400, height=400, frameRate=24, backgroundColor=0x000000)]
    public class FlashTest extends Sprite {
    	
    		public var dragFlg:Boolean = false;
        public var statusText:TextField;
        public var beginPoint:Point;
        public var lines:Vector.<Line> = new Vector.<Line>;
        public var pointCanvas:Sprite = new Sprite();	// 交点描画
        public var lineCanvas:Sprite = new Sprite();	// 線描画
        public var mainCanvas:Sprite = new Sprite();	// 3D描画
        public var crossPoint:Point = new Point();
        public var mtx:Matrix3D;
        public const CX:Number = stage.stageWidth/2;
        public const CY:Number = stage.stageHeight/2;
        public var vertices:Vector.<Number>;
        public var indices:Vector.<int>;
        public var uvt:Vector.<Number>;
        
        public function FlashTest() {
 
            // 状態表示(基本動作には不要)
        		statusText = new TextField();
        		statusText.width = stage.stageWidth;
        		statusText.text = '';
        		statusText.selectable = false;
        		addChild(statusText);
        		
        		// 3D表示用カンバス
        		addChild(mainCanvas);
        		mainCanvas.x = CX;
        		mainCanvas.y = CY;
        		mainCanvas.z = 0;

        		// 線描画用カンバス
        		addChild(lineCanvas);
        		lineCanvas.z = 0;
        		// 交点表示用カンバス
        		addChild(pointCanvas);
        		
        		// イベント検知
        		stage.addEventListener(MouseEvent.MOUSE_UP,   xStopDrag);
        		stage.addEventListener(MouseEvent.MOUSE_MOVE, xDrawLine);
        		stage.addEventListener(MouseEvent.MOUSE_DOWN, xStartDrag);
        }
        
        // 描画開始
        public function xStartDrag(e:MouseEvent):void {
        		statusText.text = 'start';	// 状態表示
        		dragFlg = true;
        		lineCanvas.graphics.clear();
        		lineCanvas.graphics.lineStyle(3,0xcccccc);
        		var nX:Number = mouseX;
        		var nY:Number = mouseY;
        		lineCanvas.graphics.moveTo(nX, nY);
        		// linesを初期化
        		lines.splice(0, lines.length);
        		// 描画開始点を記録
        		beginPoint = new Point(nX, nY);
        		// メインカンバス初期化
			mainCanvas.graphics.clear();	// 後で修正
        }
        
        // 描画中
		// マウスが動いたことを検知し
		// かつマウスが押されている場合(dragFlg==true)だけドラッグと判断する
        public function xDrawLine(e:MouseEvent):void {
        		if (dragFlg) {
	        		statusText.text = 'drag';	// 状態表示
	        		xDrawAndRecord();
        		}
        }
        
        // 描画終了
        public function xStopDrag(e:MouseEvent):void {
        		statusText.text = 'stop';	// 状態表示
        		dragFlg = false;
        		xDrawAndRecord();
        		var nL:Number = lines.length;
	        	statusText.text = nL.toString();	//lines;
	        	
	        	// マウス反応を停止
        		stage.removeEventListener(MouseEvent.MOUSE_UP,   xStopDrag);
        		stage.removeEventListener(MouseEvent.MOUSE_MOVE, xDrawLine);
        		stage.removeEventListener(MouseEvent.MOUSE_DOWN, xStartDrag);

        		// 3D化
	        vertices = new Vector.<Number>();
	        	indices = new Vector.<int>();
	        	uvt = new Vector.<Number>();
	        	// Linesから座標値を取り出す
	        	// 交点が複数存在する場合は、開始点から近い順に取り出す
	        	var totalCount:uint = lines.length;
	        	// 最初のLineから描画開始点を取り出して
	        	vertices.push(lines[0].p1.x, lines[0].p1.y, 50);
	        	vertices.push(lines[0].p1.x, lines[0].p1.y, -50);
	        	for (var i:uint = 1; i < totalCount; i++) {
			    	// 以降交点と描画終了点を取り出す
		        	vertices.push(lines[i].p2.x-CX, lines[i].p2.y-CY, -50);
		        	// ※ Z値が異なる頂点は後処理で追加したほうが楽しい効果を得られる
		        	// ※ が、暫定版としてこのまま処理
		        	vertices.push(lines[i].p2.x-CX, lines[i].p2.y-CY, 50);
		        	indices.push(i*2+0,i*2+1,i*2+3, i*2+3,i*2+2,i*2+0);
		        	//uvt.push(0,0,0,1,1,1,0,1);
	        	}
	        	// 3D描画処理
	        	// ※drawTrianglesを用いているが、
	        	// ※陰影を表現するためにパネルを1枚ずつ描くように変更
	        	mtx = new Matrix3D();
	        	
	        	stage.addEventListener(Event.ENTER_FRAME, xRotate);
	        	
        		// 描いたラインと点を徐々に消す
        		stage.addEventListener(Event.ENTER_FRAME,xDeleteLine);
	        	
        }
        
        public function xRotate(e:Event):void {
        		mainCanvas.graphics.clear();
        		mtx.appendRotation(3,Vector3D.X_AXIS);
        		mtx.appendRotation(2,Vector3D.Y_AXIS);
        		mtx.appendRotation(1,Vector3D.Z_AXIS);
	        	var vout:Vector.<Number> = new Vector.<Number>();
	        	Utils3D.projectVectors(mtx,vertices,vout,uvt);
	        	mainCanvas.graphics.beginFill(0x99cc33,0.5);
	        	mainCanvas.graphics.drawTriangles(vout,indices,null,TriangleCulling.NEGATIVE);
	        	mainCanvas.graphics.beginFill(0x0099ff,0.5);
	        	mainCanvas.graphics.drawTriangles(vout,indices,null,TriangleCulling.POSITIVE);
        }

        // ラインを描画し、linesにLineを追加
        public function xDrawAndRecord():void {
        		var nX:Number = mouseX;
        		var nY:Number = mouseY;
	        	lineCanvas.graphics.lineTo(nX,nY);
	        	
	        // linesにlineを追加
	        	var line:Line = new Line(beginPoint.x, beginPoint.y, nX, nY); 
	        	lines.push(line);
	        	
	        	// linesとlineの交点を求める
        		var total:Number = lines.length - 3;
        		for ( var i:uint = 0; i < total; i++) {
        			var targetLine:Line = lines[i];
        			var cross:Point = new Point();
		        // 交点が見つかったら、lineに交点を記録し、描画する
        			if (getCrossPoint(lines[i],line)) {
        				// 交点追加
        				line.crossPoints.push(crossPoint);
        				lines[i].crossPoints.push(crossPoint);
        				// 交点描画
        				pointCanvas.graphics.lineStyle(2,0xffffff);
        				pointCanvas.graphics.beginFill(0xff0000);
        				pointCanvas.graphics.drawCircle(crossPoint.x, crossPoint.y, 4);
        				pointCanvas.graphics.endFill();
        			}
        		}

	        	// 描画終了点を記録
	        	beginPoint = new Point(nX, nY);
        }
        
        // 2本の直線の交点を計算
        public function getCrossPoint(lineA:Line, lineB:Line):Boolean {
        		var flg:Boolean = false;
	        	// det == 0 は平行
	        	var det:Number = lineB.f*lineA.g - lineA.f*lineB.g;
	        	if (det != 0) {
				var dx:Number = lineB.p1.x - lineA.p1.x;
				var dy:Number = lineB.p1.y - lineA.p1.y;
				var t1:Number = (lineB.f*dy - lineB.g*dx)/det;
				var t2:Number = (lineA.f*dy - lineA.g*dx)/det;
				// t1, t2の値が0~1の範囲外の場合、交点は延長線上に存在する
				if (t1 >= 0 && t1 <= 1 && t2 >= 0 && t2 <= 1) {
					crossPoint.x = lineA.p1.x + lineA.f*t1;
					crossPoint.y = lineA.p1.y + lineA.g*t1;
					flg = true;
				}
	        	}
	        	return flg;
		}
		
		// 画面に描いた線と点を削除
		public function xDeleteLine(e:Event):void {
			lineCanvas.alpha -=0.05;
			pointCanvas.alpha -= 0.05;
			if (pointCanvas.alpha <= 0) {
				lineCanvas.graphics.clear();
				pointCanvas.graphics.clear();
				lineCanvas.alpha = 1;
				pointCanvas.alpha = 1;
				// 消去が完了したら、このイベントを削除
				stage.removeEventListener(Event.ENTER_FRAME, xDeleteLine);
		        	// マウス反応を再開
		        	// ※タイミングに問題あり
	        		stage.addEventListener(MouseEvent.MOUSE_UP,   xStopDrag);
	        		stage.addEventListener(MouseEvent.MOUSE_MOVE, xDrawLine);
	        		stage.addEventListener(MouseEvent.MOUSE_DOWN, xStartDrag);
			}
		}
    }
}

import flash.geom.Point;
class Line {
	public var p1:Point;
	public var p2:Point;
	public var f:Number;
	public var g:Number;
	public var color:uint;
	public var crossPoints:Vector.<Point> = new Vector.<Point>();
	public function Line(x1:Number=0, y1:Number=0, x2:Number=0, y2:Number=0, c:uint=0):void {
		p1 = new Point(x1, y1);
		p2 = new Point(x2, y2);
		color = c;
		f = p2.x - p1.x;
		g = p2.y - p1.y;
	}
}