package
{
import away3d.objects.WirePlane;
import away3d.core.material.ISegmentMaterial;
import away3d.core.scene.ObjectContainer3D;
import away3d.core.utils.Init;
import away3d.core.material.WireColorMaterial;
import away3d.core.mesh.Segment;
import away3d.core.mesh.Vertex;
import away3d.core.material.WireframeMaterial;
import away3d.core.scene.Object3D;
import away3dPlus.objects.WireCurve;
import flash.display.BitmapData;
import away3d.core.sprite.Sprite2D;
import away3dPlus.objects.Axes;
import away3d.core.math.Number3D;
import caurina.transitions.Tweener;
/** Wire plane */
public class Tangle extends ObjectContainer3D
{
public var tscene:TangleScene;
private var wireGuage:Number = 3;
private var grid:WirePlane;
private var gridMaterial:ISegmentMaterial
private var rope0:Rope;
private var rope1:Rope;
private var ropeGuage:Number = 20;
private var segmentsW:int = 1;
private var segmentsH:int = 1;
private var width:Number = 400;
private var height:Number = 400;
private var unit:Number = 200;
private var NE:RopeEnd;
private var SE:RopeEnd;
private var NW:RopeEnd;
private var SW:RopeEnd;
private var growAxes:Array;
private var growIndex:int = 0;
private var _p:int = 0;
private var _q:int = 1;
private var cfrac:String = "0";
private var origin:Vertex;
public function Tangle(material:ISegmentMaterial, tscene:TangleScene, target:Object3D, init:Object = null)
{
name = "Tangle";
this.tscene = tscene;
init = Init.parse(init);
width = init.getNumber("width", 400, {min:0});
height = init.getNumber("height", 400, {min:0});
growAxes = [
Number3D.RIGHT,
Number3D.FORWARD,
Number3D.LEFT,
Number3D.BACKWARD
];
zero();
}
public function get growAxis():Number3D {
return growAxes[growIndex] as Number3D;
}
public function turn():void {
var t:RopeEnd = NE;
NE = NW;
NW = SW;
SW = SE
SE = t;
growIndex = (growIndex + 1) % growAxes.length;
var s:int = p;
p = -q;
q = s;
if(q < 0) {
p = -p;
q = -q;
}
cfrac = "-1/" +cfrac;
}
public function twist():void {
extendBeforeTwist(+1);
p += q;
var t:RopeEnd = NE;
NE = SE;
SE = t;
cfrac = "(1 + " + cfrac + ")";
}
public function untwist():void {
extendBeforeTwist(-1);
p -= q;
var t:RopeEnd = NE;
NE = SE;
SE = t;
cfrac = "(-1 + " + cfrac + ")";
}
public function get p():int {
return _p;
}
public function set p(n:int):void {
_p = n;
if(tscene.stage != null)
tscene.p.text = ""+n;
}
public function get q():int {
return _q;
}
public function set q(n:int):void {
_q = n;
if(tscene.stage != null)
tscene.q.text = ""+n;
}
/**
* extend the tangle with Zero
*/
public function zero():void {
rotationY = 0;
if(rope0 != null) {
removeChild(rope0);
}
if(rope1 != null) {
removeChild(rope1);
}
addChild(rope0 = new Rope({topRope:true, thickness:ropeGuage, start:new Number3D(-unit, 0, unit), end:new Number3D(unit, 0, unit)}));
addChild(rope1 = new Rope({topRope:false, thickness:ropeGuage, start:new Number3D(-unit, 0, -unit), end:new Number3D(unit, 0, -unit)}));
growIndex = 0;
NW = rope0.ropeStart;
NE = rope0.ropeEnd;
SW = rope1.ropeStart;
SE = rope1.ropeEnd;
p = 0;
q = 1;
cfrac = "0";
tscene.resetView();
}
public function extendBeforeTwist(sense:int):void {
var edge:Number3D = Number3D.sub(NE.position, SE.position);
var growth:Number = edge.modulo;
var growthVector:Number3D = Number3D.scale(growAxis, growth);
var pos:Number3D = Number3D.add(NE.position, growthVector);
var v:Vertex = new Vertex(pos.x, pos.y, pos.z);
if(cfrac != "0")
NE.extendTo(v, NE.rope.segments);
trace("NE -> " + pos);
pos = Number3D.add(SE.position, growthVector);
v = new Vertex(pos.x, pos.y, pos.z);
if(cfrac != "0")
SE.extendTo(v, SE.rope.segments);
trace("SE -> " + pos);
var upAxis:Number3D = Number3D.cross(edge, growthVector);
upAxis.normalize(1/growth);
if(sense > 0) {
twistEnd(NE, Number3D.scale(upAxis,-1), edge);
twistEnd(SE, upAxis, Number3D.scale(edge, -1));
}
else {
twistEnd(NE, upAxis, edge);
twistEnd(SE, Number3D.scale(upAxis,-1), Number3D.scale(edge, -1));
}
tscene.invalidate();
}
public function twistEnd(end:RopeEnd, upAxis:Number3D, edge:Number3D):void {
var rope:Rope = end.rope;
var x0:int = end.index;
var inc:int = (x0 == 0) ? 1 : -1;
for (var i:int = 0; i < rope.segments+1; i++) {
var x:int = Math.round(x0 + i*inc);
var v:Vertex = rope.wire.vertex(x);
trace(x + " : " + v.position + " : " + (i - rope.segments)/(rope.segments));
var lambda:Number = (i-rope.segments)/rope.segments;
var edgeMove:Number3D = Number3D.scale(edge, lambda);
var upMove:Number3D = Number3D.scale(upAxis, Math.sin(Math.PI*i/rope.segments)/3);
var combined:Number3D = Number3D.add(edgeMove, upMove);
var newPos:Number3D = Number3D.add(v.position, combined);
trace(x + " : " + v.position + " :-> " + newPos + " lambda="+(i - rope.segments)/(rope.segments));
tscene.startTween();
Tweener.addTween(v, {x:newPos.x, y:newPos.y, z:newPos.z, time:1, transition:"easeInOutCubic", onComplete:tscene.endTween});
}
end.touch();
}
/**
* Update tangle prior to a render
*/
public function preRender():void {
var thickness:Number = ropeGuage/tscene.zoomFactor;
rope0.thickness = thickness;
rope1.thickness = thickness;
}
}
}