forked from: 平面に描いた線を3D化(Kraft Type)

by ohisama forked from 平面に描いた線を3D化(Kraft Type) (diff: 191)
マウスで引いた線を立体にする
マウスを押して動かしている間線を描いて
マウスを離したら3D化
----------------------------------------
ToDo 鋭利な角度をつけた時におかしな表示となる
(現在の深度は3D座標のZ値による)
透視投影にする
ソースが散らかっている。。。。
etc. etc...

“見た目以外には”線を引きながら交点を得る必要はない。
座標を整えるときに交点を入れる

先頭→交点、交点→交点、…、交点→終点の集合データとすると
交点は“柱”。“柱”間を壁でつなぐ
リボンのような連続した画像を貼る時、面倒に…ならない! はず。
♥0 | Line 317 | Modified 2013-02-03 15:38:43 | MIT License
play

ActionScript3 source code

/**
 * Copyright ohisama ( http://wonderfl.net/user/ohisama )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/AbIP
 */

// forked from Kay's 平面に描いた線を3D化(Kraft Type)
// forked from Kay's 平面に描いた線を3D化(暫定Ver)
// forked from Kay's ドラッグして描いた線の交差判定 
// forked from Kay's Basic お絵かき
/*
 * マウスで引いた線を立体にする
 * マウスを押して動かしている間線を描いて
 * マウスを離したら3D化
 *----------------------------------------
 * ToDo 鋭利な角度をつけた時におかしな表示となる
 *      (現在の深度は3D座標のZ値による)
 *      透視投影にする
 *      ソースが散らかっている。。。。
 *      etc. etc...
 *
 * “見た目以外には”線を引きながら交点を得る必要はない。
 * 座標を整えるときに交点を入れる
 *
 * 先頭→交点、交点→交点、…、交点→終点の集合データとすると
 * 交点は“柱”。“柱”間を壁でつなぐ
 * リボンのような連続した画像を貼る時、面倒に…ならない! はず。
 */

package 
{
    import flash.display.*;
    import flash.events.*;
    import flash.text.*;
    import flash.geom.*;
    [SWF(width=400,height=400,frameRate=30,backgroundColor=0x333333)]
    public class Take06 extends Sprite 
    {
        public const CX : Number = stage.stageWidth / 2;
        public const CY : Number = stage.stageHeight / 2;
        public var vertices2D : Vector.<Vertex>;
        public var vertices3D : Vector.<Number>;    
        public var uvt : Vector.<Number> = new Vector.<Number>();
        public var dragFlg : Boolean = false;
        public var beginPoint : Point;
        public var lines : Vector.<Line> = new Vector.<Line>();
        public var canvas2D : Sprite = new Sprite();
        public var canvas3D : Sprite = new Sprite();
        public var crossPoint : Point = new Point();
        public var mtx : Matrix3D;
        public var normals : Vector.<Vector3D>;
        public var panels : Vector.<Panel>;
        public function Take06() 
        {
            vertices2D = new Vector.<Vertex>;
            addChild(canvas3D);
            canvas3D.x = CX;
            canvas3D.y = CY;
            addChild(canvas2D);
            stage.addEventListener(MouseEvent.MOUSE_UP, xStopDrag);
            stage.addEventListener(MouseEvent.MOUSE_MOVE, xDrawLine);
            stage.addEventListener(MouseEvent.MOUSE_DOWN, xStartDrag);
        }
       public function xStartDrag(e : MouseEvent) : void 
        {
            if (dragFlg == false) 
            {
                dragFlg = true;
                var nX : Number = mouseX;
                var nY : Number = mouseY;
                canvas3D.graphics.clear();
                canvas2D.graphics.clear();
                canvas2D.graphics.lineStyle(1,0xcccccc);
                canvas2D.graphics.moveTo(nX, nY);
                lines.splice(0, lines.length);
                vertices2D.splice(0, vertices2D.length);
                beginPoint = new Point(nX, nY);
            }
        }
        public function xDrawLine(e : MouseEvent) : void 
        {
            if (dragFlg) 
            {
                xDrawAndRecord();
            }
        }
        public function xStopDrag(e : MouseEvent) : void 
        {
            dragFlg = false;
            xDrawAndRecord();
            stage.removeEventListener(MouseEvent.MOUSE_UP, xStopDrag);
            stage.removeEventListener(MouseEvent.MOUSE_MOVE, xDrawLine);
            stage.removeEventListener(MouseEvent.MOUSE_DOWN, xStartDrag);
            stage.addEventListener(Event.ENTER_FRAME,xDeleteLine);
            xGainPoints();
            vertices3D = new Vector.<Number>();
            panels = new Vector.<Panel>();    
            var vL : uint = vertices2D.length;
            var max : int = 0;
            for (var i : uint = 0; i < vL; i++) 
            {
                vertices3D.push(vertices2D[i].x, vertices2D[i].y, 0);
                if (i < vL - 1) 
                {
                    var panel : Panel = new Panel();
                    var p1 : int = i;
                    var p2 : int = i + 1;
                    var p3 : int = vL + i;
                    var p4 : int = vL + i + 1;
                    if (p4 > max) max = p4;
                    panel.ind = new Vector.<int>();
                    panel.ind.push(p1, p2, p4, p4, p3, p1);
                    var dx : Number = vertices2D[i + 1].x - vertices2D[i].x;
                    var dy : Number = vertices2D[i + 1].y - vertices2D[i].y;
                    panel.normal = new Vector3D(dx, dy, 0, 0);
                    panels.push(panel);
                }
            }
            var vUpper : Vector.<Number> = new Vector.<Number>();
            var vBottom : Vector.<Number> = new Vector.<Number>();
            var vMatrix : Matrix3D = new Matrix3D();
            vMatrix.prependTranslation(-CX, -CY, -60);
            vMatrix.transformVectors(vertices3D, vUpper);
            vMatrix.prependTranslation(0, 0, 120);
            vMatrix.transformVectors(vertices3D, vBottom);
            vertices3D = vUpper.concat(vBottom);
            mtx = new Matrix3D();
            stage.addEventListener(Event.ENTER_FRAME, xRotate);
        }
   public function xGainPoints() : void 
   {
            var lLen : Number = lines.length;
            for (var l : uint = 0; l < lLen; l++) 
            {
                for (i = l + 2; i < lLen; i++) 
                {
                    var targetLine : Line = lines[i];
                    if (getCrossPoint(lines[i], lines[l])) 
                    {
                        var cp : Point = crossPoint.clone();
                        lines[l].crossPoints.push(cp);
                        lines[i].crossPoints.push(cp);
                    }
                }
            }
            vertices2D.splice(0, vertices2D.length);   
            vertices2D.push(new Vertex(lines[0].p1.x, lines[0].p1.y));
            for (i = 0; i < lLen; i++) 
            {
                var cpLen : int = lines[i].crossPoints.length;
                if (cpLen > 0) 
                {
                    var aSort : Array = new Array();
                    var basePoint : Point = lines[i].p1;
                    for (var p : uint = 0; p < cpLen; p++) 
                    {
                        var tp : Point = lines[i].crossPoints[p];
                        var dist : Number = Point.distance(basePoint,tp);
                        aSort.push({num:p, point : tp, dist : dist});
                    }
                    aSort.sortOn("dist", Array.NUMERIC);
                    for (p = 0; p < cpLen; p++) 
                    {
                        lines[i].crossPoints.push(lines[i].crossPoints[aSort[p]['num']]);
                        vertices2D.push(new Vertex(lines[i].crossPoints[p].x, lines[i].crossPoints[p].y, 0, true));
                    }
                }
                vertices2D.push(new Vertex(lines[i].p2.x, lines[i].p2.y));
            }
            var vLen : Number = vertices2D.length;
            for (i = 1; i < vLen; i++) 
            {
                var dx : Number = vertices2D[i - 1].x - vertices2D[i].x;
                var dy : Number = vertices2D[i - 1].y - vertices2D[i].y;
                vertices2D[i].r = Math.atan2(dy,dx);
                if (i > 1) 
                {
                    vertices2D[i].d = getDifRad(vertices2D[i].r,vertices2D[i-1].r);
                }
            }
            var tempVertices2D : Vector.<Vertex> = new Vector.<Vertex>();
            tempVertices2D.push(new Vertex(vertices2D[0].x,vertices2D[0].y));
            var vTemp : Vertex = new Vertex(vertices2D[0].x,vertices2D[0].y);
            for (var i : uint = 1; i < vLen; i++) 
            {
                if (vertices2D[i].v || vertices2D[i].d>0.8) 
                {
                    tempVertices2D.push(vertices2D[i]);
                    vTemp = vertices2D[i];
                } 
                else 
                {
                    dist = Point.distance(vTemp, vertices2D[i]);
                    if (dist > 10) 
                    {
                        tempVertices2D.push(vertices2D[i]);
                        vTemp = vertices2D[i];
                    }
                }
            }
            vertices2D = tempVertices2D;
        }
   public function getDifRad(r1 : Number = 0, r2 : Number = 0) : Number 
   {
            var dr : Number = r1 - r2;
            while (dr < 0) 
            {
                dr += Math.PI * 2;
            }
            dr %= Math.PI * 2;
            dr -= dr > Math.PI ? Math.PI * 2 : 0;
            return dr;
        }
        public function xRotate(e : Event) : void 
        {
            canvas3D.graphics.clear();
            mtx.appendRotation(3, Vector3D.X_AXIS);
            mtx.appendRotation(2, Vector3D.Y_AXIS);
            mtx.appendRotation(1, Vector3D.Z_AXIS);
            var vmtx3D : Vector.<Number> = new Vector.<Number>();
            mtx.transformVectors(vertices3D, vmtx3D);
            var vout2D : Vector.<Number> = new Vector.<Number>();
            Utils3D.projectVectors(mtx, vertices3D, vout2D,uvt);
            var pLen : uint = panels.length;
            for (var p : uint = 0; p < pLen; p++) 
            {
                panels[p].zSum = (vmtx3D[panels[p].ind[0] * 3 + 2] +
                                  vmtx3D[panels[p].ind[1] * 3 + 2] +
                                  vmtx3D[panels[p].ind[2] * 3 + 2] +
                                  vmtx3D[panels[p].ind[3] * 3 + 2]);
            }
            var func:Object = function(a : Panel, b : Panel) : Number
            {
                if (a.zSum == b.zSum) return 0;
                if (a.zSum < b.zSum) return 1;
                return -1;
            }
            panels.sort(func);
       while (canvas3D.numChildren) 
       {
                canvas3D.removeChildAt(0);
            }
            var lNormal : Vector3D = new Vector3D(-1, 1, 1, 0); 
            for (p = 0; p < pLen; p++) 
            {
                var surface : Shape = new Shape();
                var rand : uint = Math.floor(Math.random() * 0xffffff);
                var vNormal : Vector3D = mtx.transformVector(panels[p].normal);
                var ratio : Number = (Vector3D.angleBetween(lNormal, vNormal) / Math.PI) / 5;
                canvas3D.addChild(surface);
                var nC : uint = Math.floor(ratio * 0xff + 0x66);
                var nColor : uint = nC + 0x22 << 16 | nC + 0x22 << 8 | nC;
                surface.graphics.beginFill(nColor);
                surface.graphics.drawTriangles(vout2D, panels[p].ind, null, TriangleCulling.POSITIVE);
                surface.graphics.endFill();
                nColor = nC + 0x22 + 0 << 16 | nC+0x11 << 8 | nC - 0x11;
                surface.graphics.beginFill(nColor);
                surface.graphics.drawTriangles(vout2D, panels[p].ind, null, TriangleCulling.NEGATIVE);
                surface.graphics.endFill();
            }
        }
        public function xDrawAndRecord() : void 
        {
            var nX : Number = mouseX;
            var nY : Number = mouseY;
            canvas2D.graphics.lineTo(nX, nY);
            var line : Line = new Line(beginPoint.x, beginPoint.y, nX, nY);
            lines.push(line);
            beginPoint = new Point(nX, nY);
        }
        public function getCrossPoint(lineA : Line, lineB : Line) : Boolean 
        {
            var flg : Boolean = false;
            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;
                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 
        {
            canvas2D.alpha -= 0.1;
            if (canvas2D.alpha <= 0.5) 
            {
                stage.addEventListener(MouseEvent.MOUSE_UP, xStopDrag);
                stage.addEventListener(MouseEvent.MOUSE_MOVE, xDrawLine);
                stage.addEventListener(MouseEvent.MOUSE_DOWN, xStartDrag);
                canvas2D.graphics.clear();
                canvas2D.alpha = 1;
                stage.removeEventListener(Event.ENTER_FRAME, xDeleteLine);
            }
        }
    }
}
import flash.geom.*;
import flash.display.*;
class Panel 
{
    public var dist : Number;
    public var normal : Vector3D;
    public var ind : Vector.<int>;
    public var zSum : Number;
    public var uvt : Vector.<Number> = new Vector.<Number>(1);
    public function Panel() : void 
    {
    }
}
class Vertex extends Point 
{
    public var r : Number = -1;
    public var v : Boolean = false;
    public var d : Number = 0;
    function Vertex(nX : Number = 0, nY : Number = 0, nR : Number = 0, bV : Boolean = false, nD : Number = 0) : void 
    {
        x = nX;
        y = nY;
        r = nR;
        v = bV;
        d = nD;
    }
}
class Line extends Shape 
{
    public var p1 : Point;
    public var p2 : Point;
    public var f : Number;
    public var g : Number;
    public var crossPoints : Vector.<Point> = new Vector.<Point>();
    public function Line(x1 : Number = 0, y1 : Number = 0, x2 : Number = 0, y2 : Number = 0) : void 
    {
        p1 = new Point(x1, y1);
        p2 = new Point(x2, y2);
        f = p2.x - p1.x;
        g = p2.y - p1.y;
    }
}