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

Stardust in a Klein Bottle

Draws Klein Bottle using Stardust Particle Engine.
see also: http://en.wikipedia.org/wiki/Klein_bottle
Get Adobe Flash player
by wellflat 19 Dec 2010
/**
 * Copyright wellflat ( http://wonderfl.net/user/wellflat )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/6RzY
 */

package {
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.filters.BlurFilter;
  import flash.filters.GlowFilter;
  import idv.cjcat.stardust.common.clocks.SteadyClock;
  import idv.cjcat.stardust.threeD.renderers.DisplayObjectRenderer3D;
  
  [SWF(width = 465, height = 465, backgroundColor = 0x00, frameRate = 30)]
  /**
   * Draws Klein Bottle using Stardust Particle Engine.
   * see also: http://en.wikipedia.org/wiki/Klein_bottle
   */
  public class Main extends Sprite {
    private var size:int;
    private var container:Sprite;
    private var emitter:KleinBottleEmitter;
    private var renderer:DisplayObjectRenderer3D;

    public function Main():void {
      Wonderfl.capture_delay(20);
      stage.scaleMode = "noScale";
      stage.align = "TL";
      size = stage.stageWidth;  // required square stage
      graphics.beginFill(0);
      graphics.drawRect(0, 0, size, size);
      container = new Sprite();
      container.x = container.y = size/2;
      container.filters = [new GlowFilter(0x0099ff), new BlurFilter(2, 2, 1)];
      addChild(container);

      emitter = new KleinBottleEmitter(new SteadyClock(1), size);
      renderer = new DisplayObjectRenderer3D(container);
      renderer.addEmitter(emitter);
      
      addEventListener(Event.ENTER_FRAME, draw, false, 0, true);
    }
    // control camera and plot point.
    private function draw(e:Event):void {
      rotate();
      emitter.plot();
    }
    private function rotate():void {
      var pi:Number = Math.PI;
      var theta:Number = 1.00 * (mouseX - size/2)*pi/180;
      var phy:Number = 0.80 * (mouseY - size/2)*pi/180;
      var lb:Number = -0.45*pi, ub:Number = 0.45*pi;
      if(phy < lb) phy = lb;
      if(phy > ub) phy = ub;
      var r:Number = 800;
      var cp:Number = Math.cos(phy);
      var x:Number = r*Math.sin(theta)*cp;
      var y:Number = r*Math.sin(phy);
      var z:Number = -r*Math.cos(theta)*cp;
      renderer.camera.position.x = x;
      renderer.camera.position.y = y;
      renderer.camera.position.z = z;
      renderer.camera.direction.set(-x, -y, -z);
    }
  }
}
        

  import idv.cjcat.stardust.common.actions.*;
  import idv.cjcat.stardust.common.actions.triggers.DeathTrigger;
  import idv.cjcat.stardust.common.clocks.Clock;
  import idv.cjcat.stardust.common.initializers.*;
  import idv.cjcat.stardust.common.math.UniformRandom;
  import idv.cjcat.stardust.threeD.actions.*;
  import idv.cjcat.stardust.threeD.emitters.Emitter3D;
  import idv.cjcat.stardust.threeD.initializers.*;
  import idv.cjcat.stardust.threeD.zones.*;

  class KleinBottleEmitter extends Emitter3D {
    private const SCALE:int = 25;
    private var size:int;
    private var point:SinglePoint3D;
    // have a increase in speed of vertex access, without using Vec3D Class.
    // < x0, y0, z0, x1, y1, z1, ... >
    private var vertices:Vector.<Number>; 
    private var pos:int;
    
    public function KleinBottleEmitter(clock:Clock, size:int) {
      super(clock);
      this.size = size;
      point = new SinglePoint3D();
      addInitializer(new DisplayObjectClass3D(MaterialSeed));
      addInitializer(new Life(new UniformRandom(550, 0)));
      addInitializer(new Mask(1 | 2));
      addInitializer(new Position3D(point));
      
      var actions:CompositeAction = new CompositeAction();
      actions.mask = 1 | 2 | 4;
      actions.addAction(new Age());
      actions.addAction(new DeathLife());
      actions.addAction(new Move3D());
      addAction(actions);
      
      var spawn:Spawn3D = new Spawn3D(new UniformRandom(1, 0));
      spawn.addInitializer(new Mask(1 | 4));
      spawn.addInitializer(new DisplayObjectClass3D(MaterialSeed));
      spawn.addInitializer(new Life(new UniformRandom(20, 10)));
      spawn.addInitializer(new Velocity3D(new SphereShell(0, 0, 0, 10, 30)));
      
      var trigger:DeathTrigger = new DeathTrigger();
      trigger.mask = 2;
      trigger.addAction(spawn);
      addAction(trigger);
      
      var scaleCurve:ScaleCurve = new ScaleCurve(0, 10);
      scaleCurve.mask = 4;
      addAction(scaleCurve);
      
      // make verteces 
      vertices = new Vector.<Number>();
      pos = 0;
      var pi:Number = Math.PI;   
      var u:Number, v:Number, r:Number;
      var step:int = 8;
      for(var i:int = 0; i <= 2*pi*step; i++) {
        for(var j:int = 0; j <= 2*pi*1.6; j++) {
          u = i/step; v = j/1.6;
          r = 4*(1 - Math.cos(u)/2);
          if(u < pi) {
            vertices[pos++] = (6*Math.cos(u)*(1 + Math.sin(u)) + r*Math.cos(u)*Math.cos(v))*SCALE;
            vertices[pos++] = (16*Math.sin(u) + r*Math.sin(u)*Math.cos(v))*SCALE;
          }else if(u > pi) {
            vertices[pos++] = (6*Math.cos(u)*(1 + Math.sin(u)) + r*Math.cos(v + Math.PI))*SCALE;
            vertices[pos++] = (16*Math.sin(u))*SCALE;
          }
          vertices[pos++] = r*Math.sin(v)*SCALE;
        }
      }
      pos = 0;
    }
    public function plot():void {
      try {
        point.x = vertices[pos++];
        point.y = vertices[pos++];
        point.z = vertices[pos++];
        this.step();
      }catch(e:RangeError) {
        pos = 0;
      }
    }
  }

  import flash.display.Shape;
  class MaterialSeed extends Shape {
    public function MaterialSeed() {
      graphics.beginFill(0xffffff);
      graphics.drawCircle(0, 0, 10);
    }
  }