PQ Torus
Drawing 3D lines in flash algorithmically
Drawing 3D lines in flash algorithmically
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
pageTitle=" P Q . t o r u s "
backgroundColor="#000000" backgroundAlpha="1"
backgroundGradientColors="[#535353, #000000]"
backgroundGradientAlphas="[1.0, 1.0]"
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:xx="nu.xero.flex.*"
layout="absolute"
applicationComplete="init3D()">
<mx:Script>
<![CDATA[/*
. . P Q . t o r u s . k n o t . .
respect due to the infamous blackpawn
thanx for sharing all your math skills!
http://www.blackpawn.com/texts/pqtorus/
*/
//________________________________________________________
// imports
import org.papervision3d.core.geom.renderables.*;
import org.papervision3d.materials.special.*;
import org.papervision3d.materials.*;
import org.papervision3d.core.geom.*;
import nu.xero.flex.*;
//________________________________________________________
// vars
//enviorment vars
private var fps :FlexFPS;
private var speed :Number = .02;
private var count :Number = 0;
private var draw :Boolean = true;
private var theColor1 :uint = 0xff00ff;
private var theColor2 :uint = 0x00ff00;
private var theMix :Number = 0;
private var dir :Boolean = false;
//line vars
private var linez :Lines3D;
private var firstX :Number = 0;
private var firstY :Number = 0;
private var firstZ :Number = 0;
private var lastX :Number = 0;
private var lastY :Number = 0;
private var lastZ :Number = 0;
private var nextX :Number = 0;
private var nextY :Number = 0;
private var nextZ :Number = 0;
//math vars
private var r :Number = 0;
private var p :Number = 4;
private var q :Number = 5;
private var phi :Number = 0;
//________________________________________________________
// constructor
private function init3D():void {
//create framerate display
fps = new FlexFPS(0x000000, 0x535353, 0xFFFFFF, 0, "kb");
addChild(fps);
//setup camera
paperCanvas.view.camera.z = -400;
//create line object
linez = new Lines3D(new LineMaterial(theColor1));
paperCanvas.view.scene.addChild(linez);
//add render loop
addEventListener(Event.ENTER_FRAME, loop3D);
}
//________________________________________________________
// render loop
private function loop3D(e:Event):void {
//update framerate display
fps.update("lines.rendered: " + linez.lines.length);
//rotation
if(autoRot.selected){
linez.rotationY = count++;
}
if(mouseControl.selected){
linez.rotationX -= (mouseY-(stage.height*.5))/100;
}
if(count<315){
//calculate torus knot
phi += speed;
r = .5 * (2 + Math.sin(q * phi)) * 10;
nextX = r * Math.cos(p * phi) * 10;
nextY = r * Math.cos(q * phi) * 10;
nextZ = r * Math.sin(p * phi) * 10;
//starting positions
if(count==1){
firstX = nextX;
firstY = nextY;
firstZ = nextZ;
lastX = nextX;
lastY = nextY;
lastZ = nextZ;
}
if(theColor2 == 0x00000f){
//add solid line
linez.addLine(new Line3D(linez, new LineMaterial(theColor1), 10, new Vertex3D(lastX, lastY, lastZ), new Vertex3D(nextX, nextY, nextZ)));
} else {
//color transition
if(!dir){
if(theMix<=250){
theMix+=5;
} else {
dir=true;
}
} else {
if(theMix>5){
theMix-=5;
} else {
dir=false;
}
}
//add gradient line
linez.addLine(new Line3D(linez, new LineMaterial(theColor1*theMix), 10, new Vertex3D(lastX, lastY, lastZ), new Vertex3D(nextX, nextY, nextZ)));
}
//update last positions
lastX = nextX;
lastY = nextY;
lastZ = nextZ;
} else if(count == 315) {
//connect the final line
if(theColor2 == 0x00000f){
linez.addLine(new Line3D(linez, new LineMaterial(theColor1), 10, new Vertex3D(lastX, lastY, lastZ), new Vertex3D(firstX, firstY, firstZ)));
} else {
linez.addLine(new Line3D(linez, new LineMaterial(theColor1*theMix), 10, new Vertex3D(lastX, lastY, lastZ), new Vertex3D(firstX, firstY, firstZ)));
}
}
//render
paperCanvas.view.singleRender();
}
//________________________________________________________
// reset linez
private function setupLinez():void {
linez.material.destroy();
linez.removeAllLines();
linez.lines = [];
phi = 0;
count = 0;
p = theP.value;
q = theQ.value;
}
//________________________________________________________
// gui
private function switchMenu(dir:String):void {
if(dir == "open"){
currentState = "customColor";
colorPanel.x = btnColor.x - 40;
} else {
currentState = "";
}
}
//________________________________________________________
// change line color
private function setColor(color1:uint, color2:uint = 0x00000f):void {
theColor1 = color1;
theColor2 = color2;
setupLinez();
currentState = "";
}
//________________________________________________________
// move camera
private function fov():void {
paperCanvas.view.camera.z = theZoom.value;
}
]]>
</mx:Script>
<mx:states>
<mx:State name="customColor">
<mx:AddChild position="lastChild">
<mx:Panel x="653" width="86" height="437" layout="absolute" id="colorPanel" bottom="31" borderStyle="solid" borderColor="#c3c3c3" borderThickness="1" headerHeight="3" backgroundAlpha=".59" backgroundColor="#303030" dropShadowEnabled="false">
<mx:Button x="7" y="24" label=" " width="55" fillAlphas="[1.0, 1.0]" fillColors="[#1EFF00, #1EFF00]" id="btnLime" click="setColor(0x00ff00, 0x000000f)"/>
<mx:Button x="7" y="50" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FF0000, #FF0000]" id="btnRed" click="setColor(0xff0000, 0x000000f)"/>
<mx:Button x="7" y="77" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#0000FF, #0000FF]" id="btnBlue" click="setColor(0x0000ff, 0x000000f)"/>
<mx:Button x="7" y="104" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FF00CC, #FF00FF]" id="btnPink" click="setColor(0xff00ff, 0x000000f)"/>
<mx:Button x="7" y="132" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FFF000, #FFF000]" id="btnYellow" click="setColor(0xfff000, 0x000000f)"/>
<mx:Button x="7" y="159" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#006600, #006600]" id="btnGreen" click="setColor(0x006600, 0x000000f)"/>
<mx:Button x="7" y="186" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FFFFFF, #FFFFFF]" id="btnWhile" click="setColor(0xffffff, 0x000000f)"/>
<mx:Button x="7" y="227" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FF00FF, #00FF00]" id="btnMix1" click="setColor(0xff00ff, 0x00ff00)"/>
<mx:Button x="7" y="254" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#00FFFF, #FFF000]" id="btnMix2" click="setColor(0x00ffff, 0xfff00)"/>
<mx:Button x="7" y="333" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FF0000, #FFF000]" id="btnMix5" click="setColor(0xffff00, 0xfff00)"/>
<mx:Button x="7" y="306" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#0000FF, #00FF00]" id="btnMix4" click="setColor(0x0000ff, 0x00ff00)"/>
<mx:Button x="7" y="280" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#00FF00, #FF0000]" id="btnMix3" click="setColor(0x00ff00, 0xff0000)"/>
<mx:Button x="7" y="362" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FF0000, #000000]" id="btnMix6" click="setColor(0xff0000, 0x000000)"/>
<mx:Button x="7" y="389" width="55" fillAlphas="[1.0, 1.0]" fillColors="[#FFFFFF, #FFF000]" id="btnMix7" click="setColor(0xffffff, 0xfff00)"/>
<mx:Label x="15" y="209" text="mixed" color="#FFFFFF"/>
<mx:Label x="18" y="5" text="solid" color="#FFFFFF"/>
</mx:Panel>
</mx:AddChild>
<mx:SetProperty target="{btnColor}" name="label" value="v"/>
<mx:SetProperty target="{btnColor}" name="width" value="34"/>
<mx:SetEventHandler target="{btnColor}" name="click" handler="switchMenu("close")"/>
<mx:SetStyle target="{btnColor}" name="textRollOverColor" value="#ffffff"/>
<mx:SetStyle target="{btnColor}" name="textSelectedColor" value="#ffffff"/>
<mx:RemoveChild target="{btnColor}"/>
<mx:AddChild position="lastChild" target="{btnColor}"/>
<mx:SetStyle target="{btnColor}" name="right" value="27"/>
<mx:SetStyle target="{btnColor}" name="bottom" value="4"/>
<mx:RemoveChild target="{label1}"/>
<mx:AddChild position="lastChild" target="{label1}"/>
<mx:SetProperty target="{label1}" name="text" value="color"/>
<mx:SetStyle target="{label1}" name="bottom" value="6"/>
<mx:SetStyle target="{label1}" name="right" value="71"/>
</mx:State>
</mx:states>
<xx:CanvasView3D id="paperCanvas" top="0" bottom="0" left="0" right="0"/>
<mx:ApplicationControlBar right="0" left="0" bottom="0">
<mx:Label text=" torus ( P =" color="#FFFFFF"/>
<mx:NumericStepper width="45" id="theP" value="4" minimum="-50" maximum="50" change="setupLinez()" backgroundColor="#333333" color="#FFFFFF" borderColor="#000000"/>
<mx:Label text=", Q = " color="#FFFFFF"/>
<mx:NumericStepper width="45" id="theQ" value="5" minimum="-50" maximum="50" change="setupLinez()" color="#FFFFFF" backgroundColor="#333333" borderColor="#000000"/>
<mx:Text text=") " color="#FFFFFF"/>
<mx:Label text=" "/>
</mx:ApplicationControlBar>
<mx:Label text="color" color="#FFFFFF" id="label1" right="71" bottom="6"/>
<mx:Button label="^" width="35" color="#FFFFFF" fillAlphas="[1.0, 1.0]" fillColors="[#000000, #8B8B8B, #464646, #000000]" id="btnColor" click="switchMenu("open")" right="27" bottom="4" themeColor="#8B8B8B" textRollOverColor="#ffffff" textSelectedColor="#ffffff"/>
<mx:HSlider id="theZoom" liveDragging="true" change="fov()" maximum="0" value="-400" minimum="-800" allowTrackClick="true" width="116" horizontalCenter="-38" bottom="10"/>
<mx:Label text="camera:" color="#FCFCFC" id="label2" horizontalCenter="-116" bottom="8"/>
<mx:CheckBox label="mouse controlled" id="mouseControl" selected="false" color="#FFFFFF" bottom="4" horizontalCenter="226"/>
<mx:CheckBox label="auto rotate" id="autoRot" selected="true" color="#FFFFFF" horizontalCenter="90" bottom="5"/>
</mx:Application>