forked from: 平面に描いた線を3D化(Kraft Type)
forked from 平面に描いた線を3D化(Kraft Type) (diff: 191)
マウスで引いた線を立体にする マウスを押して動かしている間線を描いて マウスを離したら3D化 ---------------------------------------- ToDo 鋭利な角度をつけた時におかしな表示となる (現在の深度は3D座標のZ値による) 透視投影にする ソースが散らかっている。。。。 etc. etc... “見た目以外には”線を引きながら交点を得る必要はない。 座標を整えるときに交点を入れる 先頭→交点、交点→交点、…、交点→終点の集合データとすると 交点は“柱”。“柱”間を壁でつなぐ リボンのような連続した画像を貼る時、面倒に…ならない! はず。
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;
}
}