Getting psychedelic with Sandy 3D

Posted by on Sep 13, 2007 in 3D, ActionScript, Flash, Flex8 comments

Sandy 3D on acid … Created with 3ds Max combined with Dreammania’s AS3 Geom Class Exporter. Sandy 3.0 will be released in a few weeks, so the wait is almost over!! I’ve included the main class so you can see what’s going on here …

Turn on, tune in, drop out

Here are all the classes that are used.


package {
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filters.BlurFilter;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	import sandy.core.World3D;
	import sandy.core.light.Light3D;
	import sandy.core.scenegraph.Camera3D;
	import sandy.core.scenegraph.Group;
	import sandy.materials.Appearance;
	import sandy.materials.ColorMaterial;

	[SWF(width="600", height="600", backgroundColor="#000000", frameRate="48")]

	/**
	 * SandyPsychedelic.as
	 * 13 September 2007
	 * @author Dennis Ippel - http://www.rozengain.com
	 *
	 */
	public class SandyPsychedelic extends Sprite
	{
		private var world:World3D;
		private var speed:Number,
					radius1:Number, radius2:Number,	radius3:Number,
					angle1:Number, angle2:Number, angle3:Number,
					startZPos:int,
					zIncrement:int,
					currentColorIndex:uint,
					colors:Array;
		private var yingyang:YingYang,
					peaceSymbol:PeaceSymbol,
					ohm:Ohm;
		private var screenBitmapData:BitmapData;
		private var screenBitmap:Bitmap;

		/**
		 * Initialize the 3D scene and create the symbols
		 *
		 */
		public function SandyPsychedelic()
		{
			// -- set all radii to 0
			radius1 = radius2 = radius3 = 0;

			// -- give each symbol a different start angle value
			angle1 = 0;
			angle2 = 45;
			angle3 = 90;

			// -- standard symbol depth. this value is used to
			//    reset a symbol's position once it has disappeared
			//    behind the camera
			startZPos = -6000;
			// -- the speed with which a symbol flies towards the camera
			zIncrement = 100;

			// -- create an array with some psychedelic colors
			createColorArray();

			// -- create a bitmapdata object. this is used to copy
			//    what's on the screen in a given frame. this creates
			//    the illusion that there's more than 3 objects in
			//    the scene.
			screenBitmapData = new BitmapData(
				800,
				800,
				false,
				0x000000
			);
			screenBitmap = new Bitmap();
			addChild( screenBitmap );

			// -- instantiate the 3D world
			world = World3D.getInstance();
			world.container = this;
			world.root = new Group( "rootGroup" );
			world.light.setPower( Light3D.MAX_POWER );

			// -- create the camera
			world.camera = new Camera3D( 600, 600 );
 			world.camera.x = 0;
			world.camera.y = 0;
			world.camera.z = 300;
			world.camera.lookAt( 0, 0, 0 );
			world.root.addChild( world.camera );

			// -- create the Ying Yang symbol
			yingyang = new YingYang( "yingyang" );
			yingyang.appearance = new Appearance(
				new ColorMaterial( nextColor )
			);
			yingyang.appearance.frontMaterial.lightingEnable = true;
			yingyang.z = startZPos;

			// -- create the Peace symbol
			peaceSymbol = new PeaceSymbol( "peace" );
			peaceSymbol.appearance = new Appearance(
				new ColorMaterial( nextColor )
			);
			peaceSymbol.appearance.frontMaterial.lightingEnable = true;
			peaceSymbol.z = startZPos;
			peaceSymbol.visible = false;

			// -- create the Ohm symbol
			ohm = new Ohm( "ohm" );
			ohm.appearance = new Appearance(
				new ColorMaterial( nextColor )
			);
			ohm.appearance.frontMaterial.lightingEnable = true;
			ohm.z = startZPos;
			ohm.visible = false;

			// -- add the symbols to the scene
			world.root.addChild( yingyang );
			world.root.addChild( peaceSymbol );
			world.root.addChild( ohm );

			// -- start the animation loop
			addEventListener( Event.ENTER_FRAME, animate );
		}

		/**
		 * The animation loop
		 * @param event
		 *
		 */
		private function animate( event:Event ):void
		{
			// -- animate the Ying Yang symbol
			yingyang.x = Math.sin( angle1 ) * radius1;
			yingyang.y = Math.cos( angle1 ) * radius1;
			yingyang.rotateY += 8;
			yingyang.z += zIncrement;

			// -- update for the next step
			angle1 += 0.5;
			radius1 += 1;

			if( peaceSymbol.visible )
			{
				// -- animate the Peace symbol
				peaceSymbol.x = Math.sin( angle2 ) * radius2;
				peaceSymbol.y = Math.cos( angle2 ) * radius2;
				peaceSymbol.rotateY += 8;
				peaceSymbol.z += zIncrement;

				// -- update for the next step
				angle2 += 0.5;
				radius2 += 1;
			}

			if( ohm.visible )
			{
				// -- animate the Ohm symbol
				ohm.x = Math.sin( angle3 ) * radius3;
				ohm.y = Math.cos( angle3 ) * radius3;
				ohm.rotateY += 8;
				ohm.z += zIncrement;

				// -- update for the next step
				angle3 += 0.5;
				radius3 += 1;
			}

			// -- copy the current screen into a bitmapdata
			//    object.
			captureScreen();

			// -- render the 3D scene
			world.render();

			if( yingyang.z > world.camera.z )
			{
				// -- reset the position and give it a new color
				yingyang.z = startZPos;
				yingyang.appearance.frontMaterial = new ColorMaterial( nextColor );
				yingyang.appearance.frontMaterial.lightingEnable = true;
				radius1 = 0;
			} else if( yingyang.z >= startZPos * 0.3 && !peaceSymbol.visible ) {
				// -- show the Peace symbol for the first time
				peaceSymbol.visible = true;
			} else if( yingyang.z >= startZPos * 0.6 && !ohm.visible ) {
				// -- show the Ying Yang symbol for the first time
				ohm.visible = true;
			}

			if( peaceSymbol.z > world.camera.z )
			{
				// -- reset the position and give it a new color
				peaceSymbol.z = startZPos;
				peaceSymbol.appearance.frontMaterial = new ColorMaterial( nextColor );
				peaceSymbol.appearance.frontMaterial.lightingEnable = true;
				radius2 = 0;
			}

			if( ohm.z > world.camera.z )
			{
				// -- reset the position and give it a new color
				ohm.z = startZPos;
				ohm.appearance.frontMaterial = new ColorMaterial( nextColor );
				ohm.appearance.frontMaterial.lightingEnable = true;
				radius3 = 0;
			}
		}

		/**
		 * Create the color array and fill it up with
		 * psychedelic colors.
		 *
		 */
		private function createColorArray():void
		{
			colors = [
				0xff0000,
				0x00ff00,
				0xffffff,
				0xffa500,
				0xffff00,
				0x0000ff
			];
		}

		/**
		 * Get the next color from the array
		 * @return the next color
		 *
		 */
		private function get nextColor():uint
		{

			if( currentColorIndex == colors.length )
				currentColorIndex = 0;
			return colors[ currentColorIndex++ ];
		}		

		/**
		 * Store the current frame in a BitmapData object
		 * and apply a BlurFilter
		 *
		 */
		private function captureScreen():void
		{
			screenBitmapData.draw(
				this
			);
			screenBitmapData.applyFilter(
				screenBitmapData,
				new Rectangle( 0, 0, 800, 800 ),
				new Point( 0, 0 ),
				new BlurFilter( 2, 2, 1 )
			);
			screenBitmap.bitmapData = screenBitmapData;
		}
	}
}


Tags: , , , ,


8 comments

» Comments RSS Feed
  1. Hi Dennis!

    That’s a beauty :)
    Let’s have it as a demo for Sandy!

  2. Really nice. How do you do that…

  3. Wonder how I could use this to improve the user experience of my website. You guys seem to know what you are doing. Would be great if you could do some fresh postings on a frequent basis.

  4. It’s very good article. Great site with very good look and perfect information. I like it too.

  5. Nice work. Would love to have this eye catcher on my website ;-)

  6. WoW that looks really good. I wish I knew how to code like you guys ;-) My compliments.

  7. wow…just passing thru and saw this. I would LOVE to have this for a screensaver….

  8. I’m happy to tell you that Sandy 3.1 will be released very soon, probably today :)
    It is further enhanced for flexibility and with some new features.
    So go ahead and test it!

Leave a comment