forked from: forked from: ball with perlin

by path.hki forked from forked from: ball with perlin (diff: 1)
♥0 | Line 156 | Modified 2011-06-17 17:36:42 | MIT License
play

ActionScript3 source code

/**
 * Copyright path.hki ( http://wonderfl.net/user/path.hki )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/ehv1
 */

// forked from Yasu_Tana9870's forked from: ball with perlin
// forked from yshu's ball with perlin
package  
{
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.filters.BevelFilter;
	import flash.filters.DropShadowFilter;
	import flash.filters.GlowFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Matrix3D;
	import flash.geom.Utils3D;
	import flash.geom.Vector3D;
	import flash.text.TextField;
	import flash.text.TextFormat;

	// demo for http://www.meetup.com/Budapest-Flash-Meetup-Group/
	
	[SWF(backgroundColor="0x000000", frameRate="30")]
	public class BallLite extends Sprite
	{
		private var screen:Sprite
		private var radius:Number = 175

		private var texture:BitmapData
		private var noise:BitmapData

		private var vertices:Vector.<Number>
		private var indices:Vector.<int>
		private var uvtData:Vector.<Number>
		private var matrix3D:Matrix3D
		private var projectedVertices:Vector.<Number>
		
		private var fold:Number = 0
		
		private var renderMode:int = 0
		
		private var _detail:Number = 5
		private var xDetail:Number = 30
		private var yDetail:Number = 20

		private var rx:Number = 0
		private var ry:Number = 0
		private var _color:Number = 0xff
		
		private var helpTf:TextField
		private var statTf:TextField

		public function BallLite() 
		{
			addChild(screen = new Sprite())
			
			addChild(helpTf = new TextField())
			addChild(statTf = new TextField())
			helpTf.multiline = true
			helpTf.autoSize = statTf.autoSize = 'left'
			helpTf.defaultTextFormat = statTf.defaultTextFormat =  new TextFormat('verdana', 10, 0xffffff)
			helpTf.text = 'click : render mode\nctrl + click : color\n\nup / down : datail\nleft / right : fold'
			helpTf.selectable = statTf.selectable = false
			helpTf.x = helpTf.y = statTf.x = 10
			statTf.y = helpTf.y + helpTf.height + 10

			noise = new BitmapData(400, 400, true, 0xffff0000)
			noise.perlinNoise(100, 100, 1, int(Math.random() * 100), true, false, 8, true)

			texture = new BitmapData(400, 400, true, 0xff000000)

			color = 0x00ffff
			detail = 8
			initGrid()

			stage.align = 'TL'
			stage.quality= 'LOW'
			stage.scaleMode = 'noScale'
			stage.addEventListener('enterFrame', render)
			stage.addEventListener('mouseDown', onMouseDown)
			stage.addEventListener('keyDown', onKeyDown)
			stage.addEventListener('resize', onStageResize)
			onStageResize()

		}
		
		private function initGrid():void
		{
			vertices = new Vector.<Number>()
			indices = new Vector.<int>()
			uvtData = new Vector.<Number>()
			projectedVertices =  new Vector.<Number>()

			var xr:Number = 0
			var yr:Number = 0

			var xrd:Number = (Math.PI *2) / xDetail
			var yrd:Number = Math.PI  / yDetail

			var i:Number
			var r:Number

			for (var y:Number = 0; y <= yDetail ; y++ )
			{
				xr = 0
				for (var x:Number = 0; x <= xDetail; x++ )
				{
					r = radius - fold + fold * Math.random()

					vertices.push
					(
						r * Math.sin(yr) * Math.cos(xr),
						r * Math.sin(yr) * Math.sin(xr),
						r * Math.cos(yr)
					)

					uvtData.push(x / xDetail, y / yDetail, 0)

					i = y * xDetail + x + y

					if (x < xDetail && y < yDetail)
					{
						indices.push(i, i + 1, i + xDetail + 1)	
						indices.push(i + 1, i + 1 + xDetail + 1, i + xDetail + 1)
					}
					xr += xrd
				}
				yr += yrd
			}

			statTf.text = 'vertices : ' + vertices.length
		}

		private function render(...e):void
		{
			matrix3D = new Matrix3D()
			matrix3D.prependRotation( 90,	Vector3D.X_AXIS)
			matrix3D.appendRotation( rx += screen.mouseX / 10,	Vector3D.Y_AXIS)
			matrix3D.appendRotation( - screen.mouseY / 2,	Vector3D.X_AXIS)

			Utils3D.projectVectors(matrix3D, vertices, projectedVertices, uvtData)

			screen.graphics.clear()
			
			if (renderMode != 2 && texture) screen.graphics.beginBitmapFill(texture)
			if (renderMode > 0) screen.graphics.lineStyle(0, _color, .5)
			screen.graphics.drawTriangles(projectedVertices, indices, uvtData, 'negative')
		}

		public function get color():Number { return _color }
		public function set color(value:Number):void 
		{
			_color = value

			texture.fillRect(texture.rect, 0x000000ff)
			texture.draw(noise, null, new ColorTransform((_color >> 16) / 0xff, (_color >> 8 & 0xff) / 0xff, (_color & 0xff) / 0xff, 1), null, noise.rect, false)
			
			screen.filters =
			[
				new DropShadowFilter(0, 0, _color, 1, 4, 4, 1, 3, false),
				new GlowFilter(_color, 1, 20, 20, 2, 3, false),
				new BevelFilter(radius / 2, 45, 0xffffff, .5, 0, 1, radius / 2, radius / 2, 1, 3)
			]
		}

		public function get detail():Number { return _detail }
		public function set detail(value:Number):void 
		{
			xDetail = 3 * (_detail = value)
			yDetail = 2 * _detail
		}

		private function onMouseDown(e:MouseEvent):void 
		{
			if (e.ctrlKey) color = Math.random() * 0xffffff | 0x00ffff
			else if (renderMode++ > 1) renderMode = 0
		}

		private function onKeyDown(e:KeyboardEvent):void 
		{
			switch(e.keyCode)
			{
				case 37: fold = Math.min(100, fold +10 ); break
				case 39: fold = Math.max(0, fold -10 ); break
				case 38: detail = Math.min(20, _detail + 1); break
				case 40: detail = Math.max(1, _detail - 1); break
				default : return
			}

			initGrid()
		}

		private function onStageResize(...e):void
		{
			screen.x = stage.stageWidth / 2 
			screen.y = stage.stageHeight / 2 
		}
	}
}